问题描述
我想在类级别具有注释 ,以便在带注释的类中的每个方法上执行建议。 甚至有可能。
示例:我想用OmniDemoService
注释@DoSomethingForMe
,并且我希望 method1 和method2
都记录“ em>在执行之前先看看我”
此示例不起作用,我也不知道为什么。当我将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---");
}
}
解决方法
您的问题是您将切入点定义与建议混淆了。
切入点是瞄准目标,建议执行实际的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 quick reference对@annotation()
的评价:
主题具有类型注释的任何连接点
SomeAnnotation
您使用了@annotation(DoSomethingForMe)
,但是方法执行的“ subject”是方法。因此,这意味着 any 注释为@DoSomethingForMe的方法。
使用@this(DoSomethingForMe)
或@target(DoSomethingForMe)
。
感谢kriegaex指出必须在运行时对@this
和@target
进行评估,这会污染代码库很多(即,检查每个方法)。因此,下一种方法更好:
如果您查看关于type patterns的AspectJ手册部分,将会看到可以直接注释类型。还请记住使用完全限定的类名。这样就可以了:
execution(public * (@com.path.DoSomethingForMe *).*(..))
此外,如果您有一个简单的切入点并且不需要重用它,我想您可以删除其他方法,并直接在建议中使用它:
@Before("execution(public * (@com.path.DoSomethingForMe *).*(..))")
表示:“在执行任何带有@com.path.DoSomethingForMe
注释的类型的公共方法之前”,其中“在执行方法之前”是指“在方法内部,开始时”。
或者,如果这个切入点对您来说太复杂了,您可以像J Asgarov在他的评论中建议的那样,将注释匹配和方法匹配分开:
@Before("execution(public * *(..)) && @within(com.path.DoSomethingForMe)")
,
该问题的解决方案是在切入点中使用
@Pointcut("@within(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}
@J Asgarov在评论中提供的解决方案