我想在类级别进行注释,该注释将对注释类中的每个方法执行建议。 这可能吗。
示例:我想用@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("@annotation(com.omnidemo.advice.DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void logMethodCall(JoinPoint jp) {
String methodName = jp.getSignature().toShortString();
logger.info("Executing: " + methodName);
}
该问题的解决方案是使用 in 进行切入点
@Pointcut("@within(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}
@J Asgarov在评论中提供的解决方案
查看 AspectJ 快速参考对@annotation()
的看法:
主题具有类型批注的任何连接点
SomeAnnotation
您使用了@annotation(DoSomethingForMe)
但方法执行的"主题"是方法。因此,这意味着任何方法都带有注释@DoSomethingForMe。
使用@this(DoSomethingForMe)
或@target(DoSomethingForMe)
。
感谢 kriegaex 指出@this
和@target
必须在运行时进行评估,这会严重污染代码库(即检查每个方法)。所以下一个方法更好:
如果您查看有关类型模式的 AspectJ 手册部分,您会发现您可以直接注释类型。还请记住使用完全限定的类名。所以这将是:
execution(public * (@com.path.DoSomethingForMe *).*(..))
另外,如果您有如此简单的切入点并且不需要重用它,我认为您可以放弃其他方法并直接在建议中使用它:
@Before("execution(public * (@com.path.DoSomethingForMe *).*(..))")
它说:"在执行用@com.path.DoSomethingForMe
注释的任何类型的公共方法之前",其中"在执行方法之前"是指"在方法内部,开始时"。
或者,如果这个切入点对你来说看起来有点太复杂了,你可以像这样分开注释匹配和方法匹配,正如 J Asgarov 在他的评论中所建议的那样:
@Before("execution(public * *(..)) && @within(com.path.DoSomethingForMe)")