zoukankan      html  css  js  c++  java
  • shiro中部分SpringCache失效问题

    原文:https://www.cnblogs.com/liruiloveparents/p/9392159.html

    shiro中部分SpringCache失效问题

     

    1、问题抛出

    今天在做Springboot和shiro集成时,发现一个严重的问题。部分service的缓存和事务失效,debug代码时,发现这些有问题的service实例都不是代理生成的,所以事务和缓存就失效了(事务和缓存依赖代理类实现)。继续查问题,发现这些有问题的service全部被shiro的realm所依赖,所以怀疑是shiro影响了

    所以做一下测试:

    shiro中用到的ResourceService

    public class LocalRealmService extends RealmService {
        @Autowired
        private ResourceService resourceService;
        ...
    }

    controller也调用ResourceService

    @RestController
    @RequestMapping(value = "/test")
    public class CacheController {
        private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @Autowired
        private ResourceService resourceService;
    }

    结果发现resourceService的实例如图:

    发现问题:resourceService的实例不是代理即缓存注解和事务全部生效(缓存和事务都是代理完成的)

    当我把resourceService从realm依赖中删除时,在controller引用时resourceService的实例就是“代理”即缓存和事务生效

    结论:只要被shiro的realm所依赖的service,代理会全部失效(暂时没撸源码,还不知原理,知道的童鞋可以说下,谢了)

    2、解决的方案

    常用的解决方式有三种:

    第一种:这是网上比较多的

    就是realm中不要依赖service,依赖dao

    第二种:在依赖的service上添加@Lazy注解

    延迟加载,就是在实例化shiro的realm时,不去实例化service的bean,等到用的时候再从spring容器中去取对应的Bean

    public class LocalRealmService extends RealmService {
        
        @Lazy
        @Autowired
        private ResourceService resourceService;
        ...
    }

    这种解决方案让我感觉到:这里是不是存在多个上下文,或者不是spring?这里有待后续考证。。。

    第三种:shiro在实例化securityManager时,先不设置realm,等到容器加载完再设置

    这种方式与第二种类似,只不过无需在每个service属性上增加@Lazy注解

    SecurityMangaerd的实例化

    /**
    * 注释掉realm
    */
    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager(/*@Qualifier("realm") BootRealm BootRealm,*/
                                                     SessionManager sessionManager,
                                                     CacheManager shiroCacheManager) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        //注释掉
        //manager.setRealm(hyBootRealm);
    }

    容器加载完设置realm:这里有多重方案,主要列举两种

    I、利用spring监听

    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    
    @Component
    public class ShiroRealmListener implements ApplicationListener {
        @Autowired
        private DefaultWebSecurityManager securityManager;
        @Autowired
        private HyBootRealm realm;
        
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            securityManager.setRealm(realm);
        }
    }

    II、利用springboot的ApplicationRunner

    import com.chyjr.hyboot.security.shiro.realm.HyBootRealm;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.ApplicationRunner;
    
    public class ShiroRealmRunner implements ApplicationRunner {
    
        @Autowired
        private DefaultWebSecurityManager securityManager;
        @Autowired
        private HyBootRealm realm;
        
        @Override
        public void run(ApplicationArguments args) throws Exception {
            securityManager.setRealm(realm);
        }
    }

    注意:ShiroRealmRunner必须是spring的Bean,所以在配置管理类中要添加:

    @Bean
    public ShiroRealmRunner shiroRealmRunner(){
        return new ShiroRealmRunner();
    }
  • 相关阅读:
    iaas,paas,saas理解
    July 06th. 2018, Week 27th. Friday
    July 05th. 2018, Week 27th. Thursday
    July 04th. 2018, Week 27th. Wednesday
    July 03rd. 2018, Week 27th. Tuesday
    July 02nd. 2018, Week 27th. Monday
    July 01st. 2018, Week 27th. Sunday
    June 30th. 2018, Week 26th. Saturday
    June 29th. 2018, Week 26th. Friday
    June 28th. 2018, Week 26th. Thursday
  • 原文地址:https://www.cnblogs.com/shihaiming/p/9394271.html
Copyright © 2011-2022 走看看