[英]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.