1 回答

TA貢獻1802條經驗 獲得超5個贊
正如JB Nizet已經說過的那樣,@annotation(my.package.MyAnnotation)
它旨在捕獲方法上的注釋,而不是字段上的注釋,這解釋了為什么您對任何事情發生的期望都是錯誤的。
如果你想通過 AOP 找出一個類是否有一個帶有特定注釋的成員,你需要使用一個特殊的切入點,比如hasfield(@MyAnnotation * *)
.?但是這個切入點在 Spring AOP 中不可用,你需要切換到 AspectJ。get(@MyAnnotation MyType *)
如果您想通過或攔截對此類字段的讀/寫訪問,也是如此set(@MyAnnotation MyType *)
。
AspectJ 還提供了特殊的切入點
在類加載后攔截類的靜態初始化 - >
staticinitialization()
攔截構造函數執行->
MyType.new()
只要是合適的時間,您就可以使用它們來執行您的方面建議。@PostConstruct
在您的示例中,如果很明顯所有目標類都有其中一個,您還可以更輕松地掛接到方法中。
我的回答很籠統,因為你沒有詳細解釋你到底想做什么。所以請隨時提出后續問題。
更新:我檢查了你最新的問題更新。我不明白,這是針對一個非常簡單的問題的非常人為的解決方案,也不是 AOP 解決的好案例。盡管我很喜歡 AOP,但我看不出這種情況是一個橫切關注點:
它似乎只影響一個類,
InfluxDBReporter
.您正在使用一個注釋,該注釋的存在唯一目的是告訴一個方面要做什么。
更糟糕的是,您將注釋放在私有字段上,但期望外部類(在本例中為方面)對其作出反應。雖然這在技術上使用 AspectJ 是可行的,但它是糟糕的設計,因為您將私有信息泄漏到外部。
通過從您的示例類中跳過公共方法,您不會保存任何昂貴的與數據庫相關的操作,因為迭代一個空
KeySet
意味著什么都不會發生,因此也不會有任何與數據庫相關的錯誤。這里唯一真正發生的是構建器調用。它們應該很便宜。
即使假設你有更多應該跳過的公共方法,如果你確實想堅持使用這種方法,我實際上會設計這樣的 AOP 解決方案:
向您的應用程序類添加一個方法
public boolean isConnectedToDB() { return !dbs.isEmpty(); }
。在您方面,使用
@Around
建議并從那里調用布爾方法,僅joinPoint.proceed()
在有任何連接時才調用。否則不要繼續,而是什么也不做(對于void
方法)或返回一個虛擬結果null
(對于非void
方法)。
確切的解決方案取決于您是否只有這個類或多個具有類似要求的類,如果您只有public void
方法或非空方法。
此外,您提到INFLUX_DB_SERVER
但我不知道這是什么,因為我在您的代碼中的任何地方都看不到它。
最后但并非最不重要的一點是:我剛剛注意到您希望在 . 注釋的方法中發生某些事情@Pointcut
。抱歉,即使切入點沒有錯,那里也會發生一些事情,因為切入點定義只是用于實際的建議方法,例如@Before
,?@After
,?@Around
。您想要執行的操作進入通知,而不是進入切入點。我建議您在嘗試設計基于 AOP 的解決方案之前先學習 AOP 基礎知識。
添加回答
舉報