本文介紹了如何使用Java定制注釋和Spring AOP設置屬性值?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我想使用定制的Java注釋在使用Spring AOP(和/或AspectJ)的私有類屬性中插入值??焖偈纠?/p>
MyAnnotation.java:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface MyAnnotation {
}
MyController.java:
public class MyControllerImpl implements MyController {
...
@MyAnnotation
private String var1;
@Override
public String getVarExample() {
// imagine this is a REST API that gets called on @GET
// request and returns a string
System.out.println(this.var1); // <-- I'd like this to be "helloworld"
// this is just for illustration
// of course, I will want to do
// something more meaningful with
// the 'var1' variable
return "ok"; <- unimportant for this example
}
...
MyAspect.java:
@Aspect
@Component
public class MyAspect {
@Pointcut("@annotation(com.mypackage.annotation.MyAnnotation)")
public void fieldAnnotatedWithMyAnnotation() {
}
@Around("fieldAnnotatedWithMyAnnotation()")
public Object enrichVar1(ProceedingJoinPoint pjp) throws Throwable {
// problem #1 - the program never enters here
// problem #2 - I need to figure out how to set up the var1 here
// to "helloworld" , how?
return pjp.proceed();
}
...
}
我希望發生什么?
我將調用并進入getVarExample()
,在它返回后,我希望在控制臺或日志中看到";HelloWorld";。我想以某種方式使用AOP將var1
設置為自定義值。將使用@MyAnnotation
注釋的任何屬性變量都將設置為";HelloWorld";。我希望上面的例子是清楚的。
我嘗試了什么?
我確保包名稱中沒有拼寫錯誤,還擺弄了不同的AOP建議注釋,如@Around
和@Before
。我還嘗試了MyAnnotation
中的不同目標,結果是ElementType.FIELD
應該是正確的。
您能幫助我使其正常工作嗎?
我知道這是可以做到的,但在網上找不到任何可用的示例。同樣,我希望看到兩個答案:
1.如何讓切入點在MyController入口觸發?我想在MyAspect
類的enrichVar1(..)
方法內捕獲斷點。
2.如何修改MyAspect
類的enrichVar1(..)
方法中帶注釋的var1
值?
我不知道我做錯了什么。任何幫助都將不勝感激。謝謝!
在我的項目中正確設置了AOP。我之所以知道這一點,是因為我已經將AOP用于不同的事情(例如日志記錄)。
更新#1:
請注意,var1
私有變量沒有getter或setter。該變量將僅在MyControllerImpl
中使用。為了更好地說明這一點,我更改了getVarExample
的返回值。
推薦答案
如我在評論中所說:
切入點指示符
@annotation()
攔截帶注釋的方法,而不是帶注釋的字段。為此,本機AspectJ有get()
和set()
。也就是說,如果遷移到AspectJ,切入點也需要更改。但我同意,堅持使用Spring AOP并注釋getter方法而不是字段在這里可能就足夠了。
但是因為您堅持要保持控制器類不變,所以這里是本機AspectJ解決方案。請閱讀Using AspectJ with Spring Applications一章,了解如何使用@EnableLoadTimeWeaving
和JVM參數-javaagent:/path/to/aspectjweaver.jar
進行配置。
為了證明該解決方案確實獨立于Spring工作,我根本沒有使用Spring類或注釋,只使用了POJO和本機AspectJ。您只需在您的Spring應用程序中執行相同的操作。請注意,與Spring AOP方面相比,本機AspectJ方面不需要@Component
注釋。
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface MyAnnotation {}
package de.scrum_master.app;
public interface MyController {
String getVarExample();
}
package de.scrum_master.app;
public class MyControllerImpl implements MyController {
@MyAnnotation
private String var1;
@Override
public String getVarExample() {
System.out.println(this.var1);
return "ok";
}
}
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
MyController myController = new MyControllerImpl();
myController.getVarExample();
}
}
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspect {
@Pointcut("get(@de.scrum_master.app.MyAnnotation * *)")
public void fieldAnnotatedWithMyAnnotation() {}
@Around("fieldAnnotatedWithMyAnnotation()")
public Object enrichVar1(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(pjp);
return "helloworld";
}
}
運行Application
時,控制臺日志為:
get(String de.scrum_master.app.MyControllerImpl.var1)
helloworld
AspectJ手冊解釋field get and set join point signatures和field patterns的語法。
注意:我認為您的用例可能是黑客設計,而不是有效的應用程序設計。您應該重構而不是侵入這樣的應用程序。
這篇關于如何使用Java定制注釋和Spring AOP設置屬性值?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,