not eligible for getting processed by all BeanPostProcessors
2024-09-08 18:59:42
描述
这个BUG大的起源是我上线以后,在后台看日志的时候发现一行奇怪的INFO日志:
2022-06-09 23:34:24 [restartedMain] [org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376] INFO - Bean 'userServiceImpl' of type [com.markerhub.service.impl.UserServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
什么?userServiceImpl代理失效了?我于是尝试了一下,果然,这个方法直接不回滚了:
@Override
@Transactional
public void addUser(UserVo user) {
User userExist = getBaseMapper().selectOne(new QueryWrapper<User>().eq("id", user.getId()));
if (userExist == null) {//添加
user.setPassword(SecureUtil.md5(user.getPassword()));
user.setCreated(LocalDateTime.now());
user.setLastLogin(LocalDateTime.now());
boolean update = saveOrUpdate(user);
log.info("添加{}号账号结果:{}", user.getId(), update);
int i = 1 / 0;
Assert.isTrue(update, "添加失败");
} else {//修改
BeanUtil.copyProperties(user, userExist, "created", "password", "lastLogin", "username", "id");
boolean update = saveOrUpdate(userExist);
log.info("修改{}号账号结果:{}", userExist.getId(), update);
Assert.isTrue(update, "修改失败");
}
}
第12行我强行模拟了故障,但是数据库里还是保存成功了。这个是生产上的严重事故。Spring事务默认的传播级别,是当前若存在事务,就加入这个事务。saveOrUpdate是mybatis-plus的方法,已经加上了事务注解,也就是说这里事务本来必须是其作用的。
原理探究
我从网上的一篇文章发现了答案https://blog.csdn.net/feiying0canglang/article/details/119704109,问题的罪魁祸首是Shiro框架。
在使用shiro框架的时候,一般都要新建一个ShiroFilterFactoryBean配置一些配置,例如:
@Bean("shiroFilterFactoryBean")
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager,
ShiroFilterChainDefinition shiroFilterChainDefinition) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
Map<String, Filter> filters = new HashMap<>();
filters.put("jwt", jwtFilter);
shiroFilter.setFilters(filters);
Map<String, String> filterMap = shiroFilterChainDefinition.getFilterChainMap();
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
这些本身是一些固定的写法,没有太多可以改的,抄过来就行了。但是问题在于ShiroFilterFactoryBean实现了BeanPostProcessor这个接口:
public class ShiroFilterFactoryBean implements FactoryBean<AbstractShiroFilter>, BeanPostProcessor;
这个接口的实现类会在某种情况下被提前初始化,导致他不会被Sping AOP的动态代理所处理,最后的结果就是事务失效。
从打印日志看到,Realm是没有被代理的,因为Realm依赖了UserService,最后UserService页没有被代理。UserService也可能依赖了其他Service,最后就全都事务失效了。
解决
在UserService上加入@Lazy懒加载模式:
UserService userService;
@Autowired
@Lazy
private void setUserServiceImpl(UserService userService) {
this.userService = userService;
}
分析依赖,将提前加载的Service全部懒加载。
最新文章
- [leetcode] 题型整理之数字加减乘除乘方开根号组合数计算取余
- windows 下 putty 登陆服务器 显示matlab图形界面
- NOIP2000方格取数[DP]
- 见鬼了,swiper
- 开发错误11:Configuration with name ‘default’ not found
- 配置IIS,Apache,PHP过程中遇到的一些问题
- Getting Started with Blocks
- echarts入门基础,画柱型图
- linux命令基础学习
- x264测试代码
- WCF和Web Service的 区(guan)别(xi)
- python2.7处理https稍微好点的办法(坑得一笔)
- 一个相当好的状态机(DFA, 确定有限状态机)的编码实现,相当简洁漂亮
- Linux之make 、makefile的使用方法
- chrome devtools 实用快捷键
- entity framework 中一些常用的函数 转自http://www.cnblogs.com/williamzhu/
- leetcode[73] Set Matrix Zeroes 将矩阵置零
- Celery 源码解析四: 定时任务的实现
- Verilog中变量位宽注意
- mysql中截取指定字符前后的字符串