亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

字段的Spring Aspect

字段的Spring Aspect

九州編程 2023-05-10 15:12:35
我有一個要向 InfluxDB 報告的 bean。數據庫在表中INFLUX_DB_SERVER注冊了 InfluxDB。如果你看代碼你會發現 MethodreportMemory做了很多工作,它構造了一個 Measurement 并做了 call reportAll,當沒有 InfluxDB 時所有這些工作都是無用的。因此,如果沒有 InfluxDB,我們的想法是跳過這項工作。由于 public-void-methods 不返回值,因此它對周圍的應用程序沒有影響。我能做的是我可以編寫一個方法isWorkPossible并在每次調用時調用該方法。這可能遵循 KISS,但違反了 DRY。所以我喜歡使用 AOP 來歸檔它。但如果沒有注冊 InfluxDB,我喜歡跳過所有 public void 方法的執行。/** * The reporter to notify {@link InfluxDB influxDBs} for changes. */@Namedpublic class InfluxDBReporter {    /**     * Logger for reporting. For security reasons neither the username nor the     * password should be logged above {@link Level#FINER}.     */    private static final Logger LOG = Logger.getLogger(InfluxDBReporter.class.getCanonicalName());    /**     * The entitymanager to use, never <code>null</code>.     */    @PersistenceContext    private final EntityManager entityManager = null;    /**     * The registred {@link InfluxDBServer} in key and the URL in value.     */    @SkipPublicVoidMethodsIfEmpty    private final Map<InfluxDB, URL> dbs = new LinkedHashMap<>();    /**     * Initializes the connections.     */    @PostConstruct    private void connect() {        for (InfluxDBServer db : FROM(囗InfluxDBServer.class).all(entityManager)) {            try {                URL dbUrl = new URL(db.getUrl());                InfluxDB idb = InfluxDBFactory.connect(db.getUrl(), db.getUsername(), db.getPassword());                idb.setDatabase(db.getDatabaseName());                dbs.put(idb, dbUrl);            } catch (MalformedURLException e) {                LOG.log(Level.SEVERE, db.getUrl(), e);            }        }    }我希望System.out.println在實例化 bean 時運行,但它沒有。知道為什么嗎?
查看完整描述

1 回答

?
12345678_0001

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 基礎知識。


查看完整回答
反對 回復 2023-05-10
  • 1 回答
  • 0 關注
  • 113 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號