AspectJ学习笔记

  1. 介绍

    1. AspectJ是一个基于Java语言的AOP框架
    2. Spring2.0以后新增了对AspectJ切点表达支持
    3. @AspectJ是AspectJ1.5新增功能,通过JDK5注解技术,允许Bean类中定义切面,新版本Spring框架,建议使用AspectJ方式来开发AOP
    4. 主要用途:自定义开发
  2. 切入点表达式

    1. execution() 用于描述方法

      <!--创建目标类-->
      <bean id="userService" class="com.adolph.AOP.jdk.UserServiceImpl"></bean>
      
      <!--创建切面类-->
      <bean id="myAspect" class="com.adolph.AOP.jdk.MyAspect"></bean>
      
      <!--aop编程
          使用<aop:config>进行配置
          proxy-target-class="true":使用cglib代理
           <aop:pointcut>切入点,从目标对象获得具体方法
           <aop:advisor> 特殊的切面,只有一个通知和一个切入点
              advice-ref:通知引用
              pointcut-ref:切入点引用
            切入点表达式:
              execution(* com.adolph.AOP.jdk.*.*(..))
              选择方法 返回值任意  包 类名任意 方法名任意 参数任意
      -->
      <aop:config proxy-target-class="true">
          <aop:pointcut id="myPointCut" expression="execution(* com.adolph.AOP.jdk.*.*(..))"/>
          <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>
      </aop:config>
      复制代码
      1. 语法:execution(修饰符 返回值 包.类.方法(参数) throws 异常)

        1. 修饰符:一般省略
        2. 返回值:*(任意)
          1. 省略
            1. con.adolph.cn 固定包
            2. com.adolph. adolph包下面子包任意*
            3. com.adolph.. adolph包下面的所有子包(含自己)
          1. 省略
          2. UserServiceImpl 指定类
          3. *Impl 以Impl结尾
          4. User 以User开头*
          5. *. 任意
        3. 方法名
          1. 不能省略
          2. addUser 固定方法
          3. add 以add开头*
          4. *Do 以Do结尾
          5. *. 任意
        4. 参数
          1. () 无参
          2. (int) 一个整型
          3. (int,int) 两个
          4. (..) 参数任意
        5. throws
          1. 可省略,一般不写
      2. 综合

           `execution(* com.adolph.AOP.jdk.*.*(..))`
        复制代码
  3. AspectJ通知类型

    1. aop联盟定义通知类型,具有特性接口,必须实现,从而确定方法名称
    2. aspectj 通知类型,只定义类型名称。以及方法格式
    3. 个数:6种,知道5种,掌握一种
      1. before:前置通知
      2. afterReturning:后置通知(应用:常规数据处理)
      3. around:环绕通知(应用:十分强大,可以做任何事情)
        1. 方法执行前后分别执行、可以阻止方法的执行
        2. 必须手动执行目标方法
      4. afterThrowing:抛出异常通知(应用:包装异常信息)
      5. after:最终通知(应用:清理现场)
  4. 基于XML

    1. 目标类:接口+实现

    2. 切面类:编写多个通知,采用aspectJ通知名称任意(方法名任意)

    3. aop编程:将通知应用到目标类

    4. 测试

    5. 目标类

      public class UserServiceImpl {
          public void addUser() {
              System.out.println("addUser");
          }
      
          public void updateUser() {
              System.out.println("updateUser");
          }
      
          public void deleteUser() {
              System.out.println("deleteUser");
          }
      }
      复制代码
    6. 切面类

      /**
       * 切面类,含有多个通知
       */
      public class MyAspect {
      
          public void myBefore(JoinPoint joinPoint) {
              System.out.println("前置通知" + joinPoint.getSignature().getName()); //获得目标方法名
          }
      
          public void myAfterReturning(JoinPoint joinPoint, Object ret) {
              System.out.println("后置通知" + joinPoint.getSignature().getName() + "____" + ret); //获得目标方法名
          }
      
          public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
              System.out.println("前");
              //手动执行目标方法
              Object proceed = joinPoint.proceed();
              System.out.println("后");
              return proceed;
          }
      
          public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){
              System.out.println("抛出异常通知:");
          }
      
          public void after(JoinPoint joinPoint){
              System.out.println("最终");
          }
      }
      复制代码
    7. xml

      <!--创建目标类-->
      <bean id="userService" class="com.adolph.AOP.jdk.UserServiceImpl"></bean>
      
      <!--创建切面类-->
      <bean id="myAspect" class="com.adolph.AOP.jdk.MyAspect"></bean>
      <!--aop编程
      -->
      <aop:config>
          <!--将切面类 声明成切面,从而获得通知(方法),ref:切面类引用-->
          <aop:aspect ref="myAspect">
              <!--声明一个切入点,所有的通知都可以使用
                  expression:切入点表达式
                  id:名称用于其他通知引用
                  -->
              <aop:pointcut id="myPointcut" expression="execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))"></aop:pointcut>
      
              <!--前置通知
              method:通知,及方法名
              pointcut:切入点表达式,此表达式只能当前通知使用
              pointcut-ref:切入点引用,可以与其他通知点共享切入点
               通知方法格式:public void myBefore(JoinPoint joinPoint)
               参数JoinPoint 用于描述连接点(目标方法),获得目标方法名称等
              -->
              <aop:before method="myBefore" pointcut-ref="myPointcut"></aop:before>
      
              <!--后置通知,目标方法执行,获得返回值
              public void myAfterReturning(JoinPoint joinPoint,Object ret)
              参数1:连接点描述
              参数2:类型Object,参数名returning配置的
              -->
              <aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut" returning="ret"></aop:after-returning>
      
              <!--环绕通知
                public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable
                返回值:Object
                方法名:任意
                参数:Proceeding JoinPoint
                抛出异常
              -->
              <aop:around method="myAround" pointcut-ref="myPointcut"></aop:around>
      
      
              <!--异常通知
              throwing:通知方法的第二个参数名称
              -->
              <aop:after-throwing method="MyAfterThrowing" pointcut-ref="myPointcut" throwing="e"></aop:after-throwing>
      
              <!--最终通知-->
              <aop:after method="after" pointcut-ref="myPointcut"></aop:after>
          </aop:aspect>
      </aop:config>
      复制代码
  5. 基于注解

    1. 替换bean

      
      <!--扫描-->
      <context:component-scan base-package="com.adolph.AOP"></context:component-scan>
      复制代码
      @Component
      public class MyAspect
      复制代码
    2. 必须进行aspectj自动代理

      <!--确定aop注解生效-->
      <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
      复制代码
    3. 声明切面

      @Component
      @Aspect
      public class MyAspect
      复制代码
    4. 设置前置通知

         @Before("execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))")
          public void myBefore(JoinPoint joinPoint) {
              System.out.println("前置通知" + joinPoint.getSignature().getName()); //获得目标方法名
          }
      复制代码
    5. 替换公共切入点

      @Pointcut("execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))")
      private void myPointCut(){
      
      }
      复制代码
    6. 设置后置通知

      @AfterReturning(value = "myPointCut()",returning = "ret")
      public void myAfterReturning(JoinPoint joinPoint, Object ret) {
          System.out.println("后置通知" + joinPoint.getSignature().getName() + "____" + ret); //获得目标方法名
      }
      复制代码
    7. 设置环绕通知

      @Around(value = "myPointCut()")
      public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
          System.out.println("前");
          //手动执行目标方法
          Object proceed = joinPoint.proceed();
          System.out.println("后");
          return proceed;
      }
      复制代码
    8. 设置抛出异常

      @AfterThrowing(value = "myPointCut()",throwing = "e")
      public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){
          System.out.println("抛出异常通知:");
      }
      复制代码
    9. 最终通知

      @AfterThrowing(value = "myPointCut()",throwing = "e")
      public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){
          System.out.println("抛出异常通知:");
      }
      复制代码

转载于:https://juejin.im/post/5ca23972e51d453c0f7d8e93

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值