一、问题描述
- Springboot整合shiro前,service里的@Cacheable、@Transactional等注解都正常使用。
- 整合shiro之后,UserServiceImpl 类里Cacheable、@Transactional等使用spring aop切入代理的注解失效
UserRealm代码如下:
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
}
UserServiceImpl 代码如下:
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
@Cacheable(cacheNames = "user", key = "#id",unless="#result == null")
public User getById(Serializable id) {
return super.getById(id);
}
}
二、解决方法
在UserRealm自动注入service时,添加@Lazy注解延迟注入,如下:
public class UserRealm extends AuthorizingRealm {
@Autowired
@Lazy
private UserService userService;
}
猜想原因:
1.Shiro框架初始化比Spring框架的某些部件早,导致使用@Autowire注入Shiro框架的某些类不能被Spring正确初始化。
2.配置shiro的时候,有用到这个配置,@Configuration里的@Bean这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
而ShiroFilterFactoryBean 实现了FactoryBean, BeanPostProcessor,相当于是实现了spring工厂,所以会先由shiro初始化,
[TRACE] - org.apache.shiro.spring.web.ShiroFilterFactoryBean.postProcessBeforeInitialization(ShiroFilterFactoryBean.java:506) - Ignoring non-Filter bean 'userServiceImpl'
看到答案因日志确实是由shiro先初始化相关用到的类,再由spring初始化剩下的,所以用到spring相关注解,就没办法生效了。我猜的,估计不准,具体原因没人知道,希望有知道的说下吧。
@Configuration
public class ShiroAutoConfiguration {
@Bean(SHIRO_FILTER)
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
factoryBean.setSecurityManager(securityManager);
// 设置未登陆的时要跳转的页面
factoryBean.setLoginUrl(loginUrl);
Map<String, String> filterChainDefinitionMap = new HashMap<>();
// 设置放行的路径
if (ArrayUtil.isNotEmpty(anonUrls)) {
for (String anonUrl : anonUrls) {
filterChainDefinitionMap.put(anonUrl, "anon");
}
}
factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return factoryBean;
}
}