描述

这个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全部懒加载。

最新文章

  1. [leetcode] 题型整理之数字加减乘除乘方开根号组合数计算取余
  2. windows 下 putty 登陆服务器 显示matlab图形界面
  3. NOIP2000方格取数[DP]
  4. 见鬼了,swiper
  5. 开发错误11:Configuration with name ‘default’ not found
  6. 配置IIS,Apache,PHP过程中遇到的一些问题
  7. Getting Started with Blocks
  8. echarts入门基础,画柱型图
  9. linux命令基础学习
  10. x264测试代码
  11. WCF和Web Service的 区(guan)别(xi)
  12. python2.7处理https稍微好点的办法(坑得一笔)
  13. 一个相当好的状态机(DFA, 确定有限状态机)的编码实现,相当简洁漂亮
  14. Linux之make 、makefile的使用方法
  15. chrome devtools 实用快捷键
  16. entity framework 中一些常用的函数 转自http://www.cnblogs.com/williamzhu/
  17. leetcode[73] Set Matrix Zeroes 将矩阵置零
  18. Celery 源码解析四: 定时任务的实现
  19. Verilog中变量位宽注意
  20. mysql中截取指定字符前后的字符串

热门文章

  1. 7.26-javascript
  2. Create React App 安装时出现的错误解决方法
  3. Linux df -h 显示磁盘空间满,但实际未占用满——问题分析
  4. Windows 11安装etcd
  5. docker 实现原理
  6. android系统签名文件路径及签名方法
  7. Java Swing 禁止黏贴动作
  8. 芯片ADS9224R的FPGA驱动实现
  9. 搭建Kubord管理k8s/EKS以及Harbor私有仓库教程
  10. noi 1.5 42画矩形