多個切面執行順序(請先看spring cache篇)

代碼https://github.com/HiwayChe/zheng/tree/develop/zheng-test

spring cache篇http://www.lxweimin.com/p/b9e85a139ea0


Cache切面在事務切面前面,只有事務執行成功才往cache中緩存數據。
代碼中共有4個切面,分別為獲取緩存失效時間,設置緩存,切換數據源,事務。
執行順序:CacheExpireAdvice.before->CacheInterceptor.invoke->MultiDataSourceAdvice.before->TransactionInterceptor.invode->MultiDataSourceAdvice.afterReturning->CacheExpireAdvice.afterReturning。
其中CacheInterceptor和TransactionInterceptor沒有before,afterReturning之分。
afterReturning只有在方法成功后才執行,如果target中拋了異常,那么afterReturning是不會執行的。如TransactionInterceptor執行失敗,CacheInterceptor是不會緩存數據的。


執行CacheTest4測試用例,日志解析如下:

@Test
    public void test(){
        String key = "fafaxxx";
        Account account;
        for(int i=0;i<2;i++){
            account = this.accountService.getAccountByName(key);
            try {
                this.logger.info("sleeping................");
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.accountService.update(key);
        this.logger.info("cache evicted....");
        for(int i=0;i<2;i++){
            account = this.accountService.getAccountByName(key);
            try {
                this.logger.info("sleeping................");
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

日志:

#執行CacheExpireAdvice.before方法,獲取緩存失效時間
01-11 00:35:27 [main] INFO  CacheExpireAdvice.before() | CacheExpireAdvice before, target method:getAccountByName
#切換數據源
01-11 00:35:27 [main] INFO  DataSourceAdvice.before() | DataSourceAdvice before,target method:getAccountByName
#當前數據源是read
01-11 00:35:27 [main] INFO  MultiDataSource.determineCurrentLookupKey() | current database:read
#由于是第一次執行,緩存中沒有數據,這里從db中查找
01-11 00:35:27 [main] INFO  AccountService.getFromDB() | =====================real querying db... fafaxxx
#清空數據源設置(到這里說明事務成功了)
01-11 00:35:27 [main] INFO  DataSourceAdvice.afterReturning() | DataSourceAdvice after,target method:getAccountByName
#db中查詢的結果緩存起來,有失效時間的
01-11 00:35:27 [main] INFO  MyRedisCache.put() | cache with expire.....
#清空失效時間值
01-11 00:35:27 [main] INFO  CacheExpireAdvice.afterReturning() | CacheExpireAdvice after, target method:getAccountByName
#代碼sleeping
01-11 00:35:27 [main] INFO  CacheTest4.test() | sleeping................
#第二次執行(這時緩存中有數據了),獲取緩存失效值
01-11 00:35:30 [main] INFO  CacheExpireAdvice.before() | CacheExpireAdvice before, target method:getAccountByName
#由于緩存中有數據了,這里直接在CacheInterceptor中返回,不再走db。清空失效值
01-11 00:35:30 [main] INFO  CacheExpireAdvice.afterReturning() | CacheExpireAdvice after, target method:getAccountByName
#代碼sleeping
01-11 00:35:30 [main] INFO  CacheTest4.test() | sleeping................
#進入到update方法(這個方法會清空緩存)。
01-11 00:35:33 [main] INFO  DataSourceAdvice.before() | DataSourceAdvice before,target method:update
#切換數據源到write
01-11 00:35:33 [main] INFO  MultiDataSource.determineCurrentLookupKey() | current database:write
01-11 00:35:33 [main] INFO  AccountService.update() | update or delete account from DB, evict from cache
#清空數據源設置
01-11 00:35:33 [main] INFO  DataSourceAdvice.afterReturning() | DataSourceAdvice after,target method:update
01-11 00:35:33 [main] INFO  CacheTest4.test() | cache evicted....
#再次讀取數據,和最上面的一樣了
01-11 00:35:33 [main] INFO  CacheExpireAdvice.before() | CacheExpireAdvice before, target method:getAccountByName
01-11 00:35:33 [main] INFO  DataSourceAdvice.before() | DataSourceAdvice before,target method:getAccountByName
01-11 00:35:33 [main] INFO  MultiDataSource.determineCurrentLookupKey() | current database:read
01-11 00:35:33 [main] INFO  AccountService.getFromDB() | =====================real querying db... fafaxxx
01-11 00:35:33 [main] INFO  DataSourceAdvice.afterReturning() | DataSourceAdvice after,target method:getAccountByName
01-11 00:35:33 [main] INFO  MyRedisCache.put() | cache with expire.....
01-11 00:35:33 [main] INFO  CacheExpireAdvice.afterReturning() | CacheExpireAdvice after, target method:getAccountByName
01-11 00:35:33 [main] INFO  CacheTest4.test() | sleeping................
01-11 00:35:36 [main] INFO  CacheExpireAdvice.before() | CacheExpireAdvice before, target method:getAccountByName
01-11 00:35:36 [main] INFO  CacheExpireAdvice.afterReturning() | CacheExpireAdvice after, target method:getAccountByName
01-11 00:35:36 [main] INFO  CacheTest4.test() | sleeping................
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,333評論 25 708
  • 你期待看到他,看到他完美的回答問題時,看到他自信的在舞臺上表現自己的時候,看到他的每個瞬間都覺得他好棒他好帥,你會...
    lorca的世界閱讀 441評論 0 0
  • 也許你猜不到 在汨汨而出的脈搏感知間 你是我藏匿了兩個秋冬春夏的心動 也許你料不及 最讓人期冀的遐想 即是做你鏡頭...
    午夜sunshine閱讀 219評論 0 3
  • 不知不覺 我已20 童年的心靈已長滿了毛刺 堅硬無比 反復感嘆 社會與我 生活和自己 然后無力 天真的想法早已打醒...
    larahe閱讀 255評論 0 1