[英]Create Pointcut for Spring AOP annotation to put annotation on class and execute advice on every method in class
我想在 class 级别上有注释,它将对注释 class中的每个方法执行建议。 这还可能吗。
示例:我想用@DoSomethingForMe
注释OmniDemoService
并且我希望method1和method2
在执行前记录“看我”
这个例子不起作用,我不知道为什么。 当我将 Pointcut 转换为 Around 并将其与注释一起使用时(还将注释 ElementType 更改为方法),一切都在方法级别上工作。 所以我认为这是错误定义的切入点。
注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoSomethingForMe {
}
建议:
@Aspect
@Component
public class DoSomethingForMeAdvice {
private static final Logger logger = LoggerFactory.getLogger(DoSomethingForMeAdvice.class);
@Pointcut("execution(public * *(..)) && @annotation(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}
}
用法:
@Service
@DoSomethingForMe
public class OmniDemoService {
private static final Logger logger = LoggerFactory.getLogger(OmniDemoService.class);
public void method1() {
logger.info("---1---");
}
public void method2() {
logger.info("---2---");
}
}
您的问题是您将切入点定义与建议混淆了。
Pointcut 是瞄准,advice 执行实际的 WhatYouWantToBeExecuted。 比如像
@Pointcut("@annotation(com.omnidemo.advice.DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void logMethodCall(JoinPoint jp) {
String methodName = jp.getSignature().toShortString();
logger.info("Executing: " + methodName);
}
查看AspectJ 快速参考中关于@annotation()
的内容:
主题具有
SomeAnnotation
类型注释的任何连接点
您使用@annotation(DoSomethingForMe)
但方法执行的“ 主题”是方法。 所以这意味着任何注释@DoSomethingForMe的方法。
使用@this(DoSomethingForMe)
或@target(DoSomethingForMe)
。
感谢kriegaex指出必须在运行时评估@this
和@target
,这会严重污染代码库(即检查每个方法)。 所以下一个方法更好:
如果你查看 AspectJ 手册中关于类型模式的部分,你会发现你可以直接注释类型。 还请记住使用完全限定的 class 名称。 所以那将是:
execution(public * (@com.path.DoSomethingForMe *).*(..))
另外,如果你有这么简单的切入点并且不需要重用它,我认为你可以放弃附加方法,直接在建议中使用它:
@Before("execution(public * (@com.path.DoSomethingForMe *).*(..))")
它说:“在执行带有@com.path.DoSomethingForMe
注释的类型的任何公共方法之前”,其中“在方法执行之前”的意思是“在方法内部,在开始时”。
或者,如果这个切入点对您来说有点过于复杂,您可以像这样将注释匹配和方法匹配分开,正如J Asgarov在他的评论中所建议的那样:
@Before("execution(public * *(..)) && @within(com.path.DoSomethingForMe)")
该问题的解决方案是使用within for pointcut
@Pointcut("@within(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}
@J Asgarov 在评论中提供的解决方案
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.