本文介紹了如何使用Java定制注釋和Spring AOP設(shè)置屬性值?的處理方法,對(duì)大家解決問(wèn)題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!
問(wèn)題描述
我想使用定制的Java注釋在使用Spring AOP(和/或AspectJ)的私有類(lèi)屬性中插入值。快速示例:
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();
}
...
}
我希望發(fā)生什么?
我將調(diào)用并進(jìn)入getVarExample()
,在它返回后,我希望在控制臺(tái)或日志中看到";HelloWorld";。我想以某種方式使用AOP將var1
設(shè)置為自定義值。將使用@MyAnnotation
注釋的任何屬性變量都將設(shè)置為";HelloWorld";。我希望上面的例子是清楚的。
我嘗試了什么?
我確保包名稱(chēng)中沒(méi)有拼寫(xiě)錯(cuò)誤,還擺弄了不同的AOP建議注釋?zhuān)?code>@Around和@Before
。我還嘗試了MyAnnotation
中的不同目標(biāo),結(jié)果是ElementType.FIELD
應(yīng)該是正確的。
您能幫助我使其正常工作嗎?
我知道這是可以做到的,但在網(wǎng)上找不到任何可用的示例。同樣,我希望看到兩個(gè)答案:
1.如何讓切入點(diǎn)在MyController入口觸發(fā)?我想在MyAspect
類(lèi)的enrichVar1(..)
方法內(nèi)捕獲斷點(diǎn)。
2.如何修改MyAspect
類(lèi)的enrichVar1(..)
方法中帶注釋的var1
值?
我不知道我做錯(cuò)了什么。任何幫助都將不勝感激。謝謝!
在我的項(xiàng)目中正確設(shè)置了AOP。我之所以知道這一點(diǎn),是因?yàn)槲乙呀?jīng)將AOP用于不同的事情(例如日志記錄)。
更新#1:
請(qǐng)注意,var1
私有變量沒(méi)有g(shù)etter或setter。該變量將僅在MyControllerImpl
中使用。為了更好地說(shuō)明這一點(diǎn),我更改了getVarExample
的返回值。
推薦答案
如我在評(píng)論中所說(shuō):
切入點(diǎn)指示符
@annotation()
攔截帶注釋的方法,而不是帶注釋的字段。為此,本機(jī)AspectJ有get()
和set()
。也就是說(shuō),如果遷移到AspectJ,切入點(diǎn)也需要更改。但我同意,堅(jiān)持使用Spring AOP并注釋getter方法而不是字段在這里可能就足夠了。
但是因?yàn)槟鷪?jiān)持要保持控制器類(lèi)不變,所以這里是本機(jī)AspectJ解決方案。請(qǐng)閱讀Using AspectJ with Spring Applications一章,了解如何使用@EnableLoadTimeWeaving
和JVM參數(shù)-javaagent:/path/to/aspectjweaver.jar
進(jìn)行配置。
為了證明該解決方案確實(shí)獨(dú)立于Spring工作,我根本沒(méi)有使用Spring類(lèi)或注釋?zhuān)皇褂昧薖OJO和本機(jī)AspectJ。您只需在您的Spring應(yīng)用程序中執(zhí)行相同的操作。請(qǐng)注意,與Spring AOP方面相比,本機(jī)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";
}
}
運(yùn)行Application
時(shí),控制臺(tái)日志為:
get(String de.scrum_master.app.MyControllerImpl.var1)
helloworld
AspectJ手冊(cè)解釋field get and set join point signatures和field patterns的語(yǔ)法。
注意:我認(rèn)為您的用例可能是黑客設(shè)計(jì),而不是有效的應(yīng)用程序設(shè)計(jì)。您應(yīng)該重構(gòu)而不是侵入這樣的應(yīng)用程序。
這篇關(guān)于如何使用Java定制注釋和Spring AOP設(shè)置屬性值?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,