Spring AOP如何编写可匹配任意深度元注解的Pointcut表达式?
问题1:Spring AOP下是否能实现任意深度元注解的切点匹配?
纯Spring AOP默认的切点表达式语法不支持直接声明任意深度的元注解匹配,但是可以通过在通知逻辑中结合Spring注解工具类做元注解递归检测的方式实现,不需要在切点表达式中写死层级,适配所有深度的元注解场景:
- 不需要写多层级的
@Pointcut规则,切点直接匹配你业务代码所在的包范围即可 - 使用Spring自带的
org.springframework.core.annotation.AnnotatedElementUtils工具类做注解检测,该工具类原生支持任意深度的元注解查找,还能处理注解属性合并、别名等特性
示例代码如下:
@Aspect @Component public class LoggableAspect { // 切点直接匹配业务包下所有类的方法,不需要做注解匹配 @Pointcut("execution(* com.your.business.package..*.*(..))") public void businessMethod() {} @Around("businessMethod()") public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); Method targetMethod = methodSignature.getMethod(); Class<?> targetClass = pjp.getTarget().getClass(); // 优先查找方法上的@Loggable(包含任意深度元注解) Loggable loggable = AnnotatedElementUtils.findMergedAnnotation(targetMethod, Loggable.class); // 方法上没有则查找类上的@Loggable(包含任意深度元注解) if (loggable == null) { loggable = AnnotatedElementUtils.findMergedAnnotation(targetClass, Loggable.class); } // 没有匹配到@Loggable则直接执行原方法 if (loggable == null) { return pjp.proceed(); } // 匹配成功,执行你的日志逻辑,直接使用loggable的配置即可 // 例如获取日志级别:loggable.value() // ... 日志逻辑 return pjp.proceed(); } }
这种方式没有层级限制,不管你把@Loggable作为几级元注解使用都能正常识别。
问题2:((@Transactional *)+)语法不生效的理解是否正确?
你的理解完全正确,该语法是原生AspectJ的专属特性,仅在使用AspectJ的编译时织入(CTW)或者加载时织入(LTW)的场景下可以生效。Spring AOP默认基于JDK动态代理/CGLIB代理实现,只适配了AspectJ切点语法的常用子集,不支持这种递归类型匹配的语法,所以在Spring AOP环境下写该表达式不会生效。
内容的提问来源于stack exchange,提问作者Cest la vie
相关产品推荐
相关产品推荐

