• Spring AOP使用整理:使用@AspectJ风格的切面声明


    要启用基于@AspectJ风格的切面声明,需要进行以下的配置:

    <!-- 启用@AspectJ风格的切面声明 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
    <!-- 通过注解定义bean。默认同时也通过注解自动注入 -->
    <context:component-scan base-package="com.cjm"/>

    基于@AspectJ风格的切面声明的源码:

    /**
     * 声明本类为一个切面
     */
    @Component
    @Aspect
    public class MyAspectJ {
        /**
         * 声明一个切入点(包括切入点表达式和切入点签名)
         */
        @Pointcut("execution(* com.cjm.model..*.*(..))")
        public void pointcut1(){}
        
        /**
         * 声明一个前置通知
         */
        @Before("pointcut1()")
        public void beforeAdvide(JoinPoint point){
            System.out.println("触发了前置通知!");
        }
        
        /**
         * 声明一个后置通知
         */
        @After("pointcut1()")
        public void afterAdvie(JoinPoint point){
            System.out.println("触发了后置通知,抛出异常也会被触发!");
        }
        
        /**
         * 声明一个返回后通知
         */
        @AfterReturning(pointcut="pointcut1()", returning="ret")
        public void afterReturningAdvice(JoinPoint point, Object ret){
            System.out.println("触发了返回后通知,抛出异常时不被触发,返回值为:" + ret);
        }
        
        /**
         * 声明一个异常通知
         */
        @AfterThrowing(pointcut="pointcut1()", throwing="throwing")
        public void afterThrowsAdvice(JoinPoint point, RuntimeException throwing){
            System.out.println("触发了异常通知,抛出了RuntimeException异常!");
        }
        
        /**
         * 声明一个环绕通知
         */
        @Around("pointcut1()")
        public Object aroundAdvice(ProceedingJoinPoint point)throws Throwable{
            System.out.println("触发了环绕通知 开始");
            Object o = point.proceed();
            System.out.println("触发了环绕通知 结束");
            return o;
        }
    }

    1、切入点表达式的格式:execution([可见性] 返回类型 [声明类型].方法名(参数) [异常])

    2、切入点表达式通配符:       *:匹配所有字符       ..:一般用于匹配多个包,多个参数       +:表示类及其子类

    3、切入点表达式支持逻辑运算符:&&、||、!

    4、切入点表达式关键词:

          1)execution:用于匹配子表达式。

                //匹配com.cjm.model包及其子包中所有类中的所有方法,返回类型任意,方法参数任意             @Pointcut("execution(* com.cjm.model..*.*(..))")             public void before(){}

          2)within:用于匹配连接点所在的Java类或者包。

                //匹配Person类中的所有方法

                @Pointcut("within(com.cjm.model.Person)")

                public void before(){}

                //匹配com.cjm包及其子包中所有类中的所有方法

                @Pointcut("within(com.cjm..*)")

                public void before(){}

           3) this:用于向通知方法中传入代理对象的引用。

                @Before("before() && this(proxy)")

                public void beforeAdvide(JoinPoint point, Object proxy){

                      //处理逻辑

                }

            4)target:用于向通知方法中传入目标对象的引用。

                @Before("before() && target(target)

                public void beforeAdvide(JoinPoint point, Object proxy){

                      //处理逻辑

                }

            5)args:用于将参数传入到通知方法中。

                @Before("before() && args(age,username)")

                public void beforeAdvide(JoinPoint point, int age, String username){

                      //处理逻辑

                }

             6)@within:用于匹配在类一级使用了参数确定的注解的类,其所有方法都将被匹配。

                @Pointcut("@within(com.cjm.annotation.AdviceAnnotation)") - 所有被@AdviceAnnotation标注的类都将匹配

                public void before(){}

      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.TYPE, ElementType.METHOD})
      @Documented
      @Inherited
      public @interface AdviceAnnotation {
    
      }

          7)@target:和@within的功能类似,但必须要指定注解接口的保留策略为RUNTIME。

                @Pointcut("@target(com.cjm.annotation.AdviceAnnotation)")

                public void before(){}

          8)@args:传入连接点的对象对应的Java类必须被@args指定的Annotation注解标注。

                @Before("@args(com.cjm.annotation.AdviceAnnotation)")

                public void beforeAdvide(JoinPoint point){

                      //处理逻辑

                }

    public class Person {
        public void say(Address address){
              //处理逻辑
       }
    }
    
     @AdviceAnnotation
     public class Address {
       
     }

      如果需要在Person类的say方法被调用时触发beforeAdvide通知,那么say方法的参数对应的Java类型Address类必须要被@AdviceAnnotation标注。

          9)@annotation:匹配连接点被它参数指定的Annotation注解的方法。也就是说,所有被指定注解标注的方法都将匹配。

                @Pointcut("@annotation(com.cjm.annotation.AdviceAnnotation)")

                public void before(){}

    public class Person {
          @AdviceAnnotation
          public void say(Address address){
                  //处理逻辑
        }
    }

      Person类的say方法被@AdviceAnnotation标注,所以它匹配。

          10)bean:通过受管Bean的名字来限定连接点所在的Bean。该关键词是Spring2.5新增的。

                @Pointcut("bean(person)")

                public void before(){}

                id为person的受管Bean中的所有方法都将匹配。

  • 相关阅读:
    c++错误:不允许使用抽象类类型 "Employee" 的对象
    C++ error C2027:使用了未定义类型 类的调用顺序
    PyCharm 2020.1 激活教程
    mysql组内排序
    XGBoost
    React学习——Hello, React
    Lambda表达式
    plsql链接远程oracle服务器,以及常用配置
    静态网站 H5 跳小程序 (短信跳小程序)
    更新(D-U-N-S)邓白氏码公司信息(注册勿看)
  • 原文地址:https://www.cnblogs.com/damowang/p/4305113.html
Copyright © 2020-2023  润新知