• Aspect 切入点 @Pointcut 语法详解


    分类pointcuts 遵循特定的语法用于捕获每一个种类的可使用连接点。

    主要的种类:
    方法执行:execution(MethodSignature)
    方法调用:call(MethodSignature)
    构造器执行:execution(ConstructorSignature)
    构造器调用:call(ConstructorSignature)
    初始化:staticinitialization(TypeSignature)
    属性读操作:get(FieldSignature)
    属性写操作:set(FieldSignature)
    例外处理执行:handler(TypeSignature)
    对象初始化:initialization(ConstructorSignature)
    对象预先初始化:preinitialization(ConstructorSignature)

    切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下:

    execution:用于匹配方法执行的连接点;
    within:用于匹配指定类型内的方法执行;
    this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
    target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
    args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
    @within:用于匹配所以持有指定注解类型内的方法;
    @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
    @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
    @annotation:用于匹配当前执行方法持有指定注解的方法;
    bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;
    reference pointcut:表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。

    AspectJ类型匹配的通配符

    *:匹配任何数量字符;
    …:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
    +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。

    举例说明

    任意公共方法的执行:
    execution(public * *(..))
    
    任何一个以“set”开始的方法的执行:
    execution(* set*(..))
    
    AccountService 接口的任意方法的执行:
    execution(* com.xyz.service.AccountService.*(..))
    
    定义在service包里的任意方法的执行:
    execution(* com.xyz.service.*.*(..))
    
    定义在service包和所有子包里的任意类的任意方法的执行:
    execution(* com.xyz.service..*.*(..))
    
    定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:
    execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")
    ***> 最靠近(..)的为方法名,靠近.*(..))的为类名或者接口名,如上例的JoinPointObjP2.*(..))
     
    pointcutexp包里的任意类.
    within(com.test.spring.aop.pointcutexp.*)
    
    pointcutexp包和所有子包里的任意类.
    within(com.test.spring.aop.pointcutexp..*)
    
    实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类.
    this(com.test.spring.aop.pointcutexp.Intf)
    ***> 当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型.
     
    带有@Transactional标注的所有类的任意方法.
    @within(org.springframework.transaction.annotation.Transactional)
    @target(org.springframework.transaction.annotation.Transactional)
    
    带有@Transactional标注的任意方法.
    @annotation(org.springframework.transaction.annotation.Transactional)
    ***> @within和@target针对类的注解,@annotation是针对方法的注解
     
    参数带有@Transactional标注的方法.
    @args(org.springframework.transaction.annotation.Transactional)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    范例

    controller

    @myLog
    @RestController
    @RequestMapping("/test")
    public class TestController {
    
        @Resource
        IMqProducerService mqProducerService;
    
        @GetMapping("/t1")
        public String t1() {
            return mqProducerService.test();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface myLog {
        String topic() default "";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    controller包下面的所有类的方法切面

    @Aspect
    @Component
    public class myLogAspect1 {
    
        @Pointcut("execution(public * org.demo.activemq.controller.*.*(..))")
        public void pointCut1() {}
    
        @After("pointCut1()")
        public void runAfter(JoinPoint joinPoint) {
            System.out.println("执行方法之后执行。。。。。");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    mylog在类上的切面

    @Aspect
    @Component
    public class myLogAspect2 {
    
        @Pointcut("@within(org.demo.activemq.mylog.myLog)")
        public void pointCut2() {
        }
    
        @Around("pointCut2()")
        public Object Around(ProceedingJoinPoint point) throws Throwable {
            System.out.println("AnnotationAspectTest Around start ");
    
            //去调用被拦截的方法
            Object proceed = point.proceed();
    
            return proceed;
        }
    
        //获取注解
        public myLog getAnnotation(ProceedingJoinPoint point) {
            Signature signature = point.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();
            if (method != null) {
                return method.getAnnotation(myLog.class);
            }
    
            return null;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    Java_Stream流式计算
    vue3+vite项目运行报错[plugin vite:dep-pre-bundle]
    月薪近万,工地转行测试,这一次的选择,真正实现了薪资翻倍~
    毕业设计 基于单片机的地震探测器系统 - stm32 物联网 嵌入式
    重建大师提交空三后引擎状态是等待,怎么开启?
    蚁群算法ACO求解连续函数极值
    Android修行手册 - 官方SearchView搭配Toolbar/样式/其他/开源项目
    225. 用队列实现栈 JavaScript实现
    protolator简介
    Java面试宝典
  • 原文地址:https://blog.csdn.net/andybegin/article/details/132970311