博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转载]Spring学习4-面向切面(AOP)之aspectj注解方式
阅读量:4478 次
发布时间:2019-06-08

本文共 4708 字,大约阅读时间需要 15 分钟。

原文地址:
作者:
一、简介
  
1、AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
   2、AOP中的概念:
   Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象.
 joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)
Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即
joinpoint的集合.
Advice(通知):
所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知
Target(目标对象):代理的目标对象
Weave(织入)
:指将aspects应用到target对象并导致proxy对象创建的过程称为织入.
Introduction(引入):
在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
   3、AOP带来的好处::降低模块的耦合度;使系统容易扩展;更好的代码复用性
二、通过注解方式实现Spring的AOP
Spring AOP环境的环境与上篇博文

Spring接口方式相同

  注解在项目中已经到处都是了,撇开一些优劣不提,开发的便利性和可读性是非常的方便的。用来配置Spring AOP也非常简单便利
步骤一、编写业务类:
@Component   //使用自动注解的方式实例化并初始化该类
public class Business {
   //
切入点
    public String delete(String obj) {
        System.out.println("==========调用切入点:" + obj + "说:你敢删除我!===========n");
        return obj + ":瞄~";
    }
    public String add(String obj) {
        System.out.println("================这个方法不能被切。。。============== n");
        return obj + ":瞄~ 嘿嘿!";
    }
    public String modify(String obj) {
        System.out.println("=================这个也设置加入切吧====================n");
        return obj + ":瞄改瞄啊!";
    }
}
步骤二、切面类:
 // @Aspect : 标记为切面类
 // @Pointcut : 指定匹配切点集合
 // @Before : 指定前置通知,value中指定切入点匹配
 // @AfterReturning :后置通知,具有可以指定返回值
// @AfterThrowing :异常通知
 //注意:前置/后置/异常通知的函数都没有返回值,只有环绕通知有返回值
@Component   //首先初始化切面类
@Aspect     //声明为切面类,底层使用动态代理实现AOP
public class AspectAdvice {
    // 指定切入点匹配表达式,注意它是以方法的形式进行声明的。
   //即切点集合是:
aop.annotation包下所有类所有方法
   //第一个* 代表返回值类型
//如果要设置多个切点可以使用 || 拼接
  @Pointcut("execution(* aop.annotation.*.*(..))|| execution(* com.action.admin.*.*update*(..))")
    public void anyMethod() {
    }
   //前置通知
   //在切点方法集合执行前,执行前置通知
   @Before("execution(* aop.annotation.*.*(..))")
    public void doBefore(JoinPoint jp) {
        System.out.println("===========进入before advice============ n");
        System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");
        System.out.print(jp.getSignature().getName() + "方法进行对 '");
        System.out.print(jp.getArgs()[0] + "'进行删除!nn");
        System.out.println("要进入切入点方法了 n");
    }
   // 后置通知
  
 @AfterReturning(value = "anyMethod()", returning = "result")
    public void doAfter(JoinPoint jp, String result) {
        System.out.println("==========进入after advice=========== n");
        System.out.println("切入点方法执行完了 n");
        System.out.print(jp.getArgs()[0] + "在");
        System.out.print(jp.getTarget().getClass() + "对象上被");
        System.out.print(jp.getSignature().getName() + "方法删除了");
        System.out.print("只留下:" + result + "nn");
    }
   // 环绕通知
(##环绕通知的方法中一定要有ProceedingJoinPoint 参数,
    //
Filter中的  doFilter方法类似
   
   @Around("execution(* aop.annotation.*.*(..))")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("===========进入around环绕方法!=========== n");
 HttpSession session = ServletActionContext.getRequest().getSession();
     Emp login =(Emp) session.getAttribute("login")
;//ssh2整合后AOP也可以得到request、response、session等
        // 调用目标方法之前执行的动作
        System.out.println("调用方法之前: 执行!n");
        // 调用方法的参数
        Object[] args = pjp.getArgs();
        // 调用的方法名
        String method = pjp.getSignature().getName();
        // 获取目标对象(形如:com.action.admin.LoginAction@1a2467a)
        Object target = pjp.getTarget();
       //获取目标对象的类名(形如:com.action.admin.LoginAction)
      String targetName = pjp.getTarget().getClass().getName();
        // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
        Object result = pjp.proceed();//result的值就是被拦截方法的返回值
        System.out.println("输出:" + args[0] + ";" + method + ";" + target + ";" + result + "n");
        System.out.println("调用方法结束:之后执行!n");
      return result;
    }
    // 异常通知
   
   @AfterThrowing(value = "execution(* aop.annotation.*.*(..))", throwing = "e")
    public void doThrow(JoinPoint jp, Throwable e) {
        System.out.println("删除出错啦");
    }
}
 步骤三、xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="    
          http://www.springframework.org/schema/beans    
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
          http://www.springframework.org/schema/context    
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/aop    
          http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    default->
    <context:component-scan base-package="aop.annotation" />
   <!-- 打开aop 注解 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
步骤四、测试类:
public class Debug {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("aop/annotation_aop.xml");
     

转载于:https://www.cnblogs.com/liuzhuqing/p/7480404.html

你可能感兴趣的文章
谷歌搜索语法
查看>>
static 静态变量
查看>>
Java面试题(05)
查看>>
操作符重载
查看>>
Docker 安装及问题处理
查看>>
JavaScript中的call 和apply的用途以及区别
查看>>
HashMap完全解读
查看>>
匿名内部类
查看>>
BZOJ4071: [APIO2015]八邻旁之桥
查看>>
Redis的六种特性 场景
查看>>
mysql 添加[取消]timestamp的自动更新
查看>>
码农的半衰期只有15年?
查看>>
手工释放linux内存
查看>>
2014-5-30 总结
查看>>
【H3 BPM工作流程管理产品小故事】第四篇 子表创建
查看>>
洛谷P1148 拱猪计分
查看>>
MySQL服务器的安装和配置,MySQL Workbench 8.0.12安装,MySQL的基本使用
查看>>
扑克序列
查看>>
java笔记--适配器模式的运用
查看>>
C#与数据结构--图的遍历
查看>>