美文网首页
多个切面执行顺序(请先看spring cache篇)

多个切面执行顺序(请先看spring cache篇)

作者: 多关心老人 | 来源:发表于2018-01-11 01:01 被阅读0次

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

    spring cache篇https://www.jianshu.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................
    

    相关文章

      网友评论

          本文标题:多个切面执行顺序(请先看spring cache篇)

          本文链接:https://www.haomeiwen.com/subject/zuoanxtx.html