使用AOP實現快取註解

2022-08-11 06:15:16 字數 1357 閱讀 2932

半年前寫了乙個註解驅動的快取,最近提交到了github。快取大量的被使用在應用中的多個地方,簡單的使用方式就是**先查詢快取中是否存在資料,如果不存在或者快取過期再查詢資料庫,並將查詢的結果快取一段時間,快取key通常是入參的物件或者入參物件的某些屬性,有些時候還需要按照某種條件判斷是否快取。可以看到這種功能性**和具體的業務**混合在一起的實現方式有很大的**冗餘,即不便於維護也不靈活。使用切面的方式可以很好的抽取功能相似**冗餘的快取**,將快取**和業務**隔離開,這樣既做到了對業務的無侵入又可以靈活更換具體快取元件。

其實從spring3之後spring就提供了@cacheable註解,但是用起來不爽的地方還是太多,例如快取時間是由cache本身設定的而非在每個@cacheable註解中指定,這個粒度有點太大了;沒有快取key的字首設定,不同方法很容易出現key衝突。

鑑於spring3提供的cache註解不太能滿足需求,最後決定自己寫乙個。目標是構造乙個簡單好用而不是大而全的快取註解,整個過程陸陸續續花了3天時間,第一天確定技術方案,構建物件和物件間的關係; 第二天寫具體的實現和debug; 第三天寫demo和test。

確定技術方案的時候看了spring3的cache註解實現和在阿里時使用過的2個cache註解實現。最大是不同點是建立**類的方式和動態生成cachekey的實現。

不同的建立**類的方式:

不同的生成cachekey的方式:

最後選擇了@aspectj+spel的實現方式。

雖然具體的實現方式各自不同,類的呼叫結構和內部功能都是基本相同的。

按照上述的功能劃分實現相關類後,花了一天的時間來寫demo和test,全部的test跑通後就可以使用了。後面增加了乙個cacheoperation轉換具體的註解,統一對cacheoperation進行處理,**簡化了不少。

實際使用中主要遇到了2個問題,乙個是interceptor中catch了所有的exception並列印錯誤日誌,實際上我們會在應用中定義bizexception,當發生預期內的錯誤時會丟擲bizexception,而bizexception是不需要被攔截列印錯誤日誌的。另乙個是問題是併發讀寫問題,在cache中沒有快取的時候,threada從db獲取資料,threadb修改了資料庫的資料,threadb刪除快取,threada然後put修改之前的資料。原本以為按照業務特點發生併發讀寫的概率不高,結果發現介面輪詢+事務導致頻繁發生不一致的情況。快取失效策略一直是快取使用中的難題,甚至是電腦科學中兩大難題之一。處理資料庫併發最常見的2個解決思路是樂觀鎖和序列化,但是並不適用於解決快取和資料庫的不一致,google了一下也沒有找到特別好的解決方案。考慮到應用並沒有超高的qps,短時間的快取穿透不會造成系統的崩潰,最後通過增加乙個redis的快取刪除標識進行解決,這個刪除標識會存活5s,在這5s中不會執行put快取操作從而避免了快取和資料庫的不一致。

使用註解實現AOP

xml標頭檔案中加入 xmlns context xsi schemalocation spring context.xsd 宣告哪些包下有註解 當有兩個以上的包時,用 隔開 在demo類中加入 component 在方法上新增 pointcut 定義切點 component public clas...

使用註解實現AOP

1.匯入jar包 與用介面實現 的jar包相同 2.配置 a.將業務類和通知類納入springioc容器 b.在容器中開啟註解對aop的支援 c.將類使用註解方式 component 放入ioc容器中時,要將該類所在的包新增到掃瞄器中 3.編寫通知類 1.加入註解 aspect,不用再實現介面 但是...

註解實現AOP

使用註解實現aop,注意版本問題,使用註解報錯要匯入m en依賴 dependency groupid j ax.annotation groupid artifactid j ax.annotation api artifactid version 1.3.2 version dependency...