SpringBoot+Shiro使用注解@RequiresPer

2018-12-31  本文已影响0人  蓝雄威

问题描述:

在写代码测试的时候,发现事务并没有起效,抛出异常之后,事务并没有回滚。但是这段代码我上星期才刚测试完,是没问题的,但是今天怎么测试都是不行.手动在启动类上贴@EnableTransactionManagement或者使用xml的方式配置事务都是不起效.
接着通过断点的方式查看该sevice对象,发现并没有被代理.
后面通过排除法的方式,发现把Shiro相关配置注释掉后就没问题了.

原因分析

在Shiro配置中,如果要@RequiresPermissions生效需要在配置文件中添加如下配置:

@Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 开启aop注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
}

DefaultAdvisorAutoProxyCreator就是通过AOP的方式对贴了@RequiredPermission的类进行增强,生成对应的代理类对象.

但是由于ShiroFilterFactoryBean实现了FactoryBean接口,所以它会提前被初始化。又因为SecurityManager,SecurityManager依赖于Realm实现类、Realm实现类又依赖于UserService,所以引发所有相关的bean提前初始化,导致UserService并没有被事务AOP包裹着.
所以就出现了事务无效的问题.

解决方案

在Realm中Service声明上加入@Lazy注解,延迟Realm实现中Service对象的初始化时间,这样就可以保证Service实际初始化的时候会被BeanPostProcessor拦截,创建具有事务功能的代理对象。

@Component
public class UserRealm extends AuthorizingRealm {
    @Autowired
    @Lazy
    private IUserService userService;
    @Autowired
    @Lazy
    private IPermissionService permissionService;
    @Override
    public String getName() {
        return "UserRealm";
    }
    .....
}
上一篇 下一篇

猜你喜欢

热点阅读