程序员

SpringBoot + Shiro导致 @Transactional 事务 和 @Async 多线程

作者:admin 2021-06-29 我要评论

我们使用的 mongoD B4.0副本集 正常是支持事务操作的但是开发运维两年 某一次发生异常但是事务并没有回滚导致数据对不上意识到需要验证下事务是否还生效单元测试...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

我们使用的 mongoD B4.0副本集 ,正常是支持事务操作的,但是开发运维两年
,某一次发生异常但是事务并没有回滚,导致数据对不上,意识到需要验证下事务是否还生效,单元测试验证 @Transactional 并未生效,查找原因,一开始以为是mongo的问题,但是两年前开始使用mongo就验证过了事务,一开始网络上找的答案都是如何配置,并未有效果,后来创建了个简单的项目,只引入相同版本spring data mongo 依赖事务生效,同时 @Async 线程异步 也生效。

同时对比了两个项目的输出日志 发现 测试 项目单元测试执行 会开启Transactional session,最后commit提交到数据库中 ,此阶段在Navicat客户端是查不到那条数据的,因为没有commit,但是 失效的项目 debug断住查看已经保存到数据库里了,不会回滚。
在这里插入图片描述

后来 感觉问题有三种可能

  1. 依赖冲突
  2. 改动过spring data mongo的源码 ,因为当时那个版本aggregate关联源码会报错,还有 保存string到数据库里是 ObjectId类型,不方便关联
  3. bean冲突

找问题 重新拉取了一样项目, 删减 依赖 改动源码 发现不是 这两个问题

然后只能一点一点删除配置的类 依赖 以及相关代码 最后发现 是shiro的问题
(此阶段 用了 两天)

就上网搜索 springboot + shiro 导致事物不生效的问题,后来找到几个博客,找到了答案

解答文章链接

总结下来就是:
由于ShiroFilterFactoryBean实现了FactoryBean接口,所以它会提前被初始化。又因为SecurityManager,SecurityManager依赖于Realm实现类、Realm实现类又依赖于UserService,所以引发所有相关的bean提前初始化。

ShiroFilterFactoryBean -> SecurityManager -> Realm实现类 -> UserService

但是此时还只是ApplicationContext中registerBeanPostProcessors注册BeanPostProcessor处理器的阶段,此时AnnotationAwareAspectJAutoProxyCreator还没有注册到BeanFactory中,UserService无法享受到事务处理!
就是说在realm中注入的所有service都会提前加载,连带注入的service中,如果还有其他service注入也会提前加载,无法享受事务处理。

解决方案:

1.在realm中注入service时,加上@lazy注解
2.不在realm注入service

@Async 注解也需要 懒加载 ,要不可能会失效

希望可以帮助到你!

;原文链接:https://blog.csdn.net/weixin_42322445/article/details/115670384

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • SpringBoot + Shiro导致 @Transactiona

    SpringBoot + Shiro导致 @Transactiona

  • SpringBoot+JavaMailSender+ 腾讯企业

    SpringBoot+JavaMailSender+ 腾讯企业

  • Kubernetes二进制部署

    Kubernetes二进制部署

  • [译] APT分析报告:09.伊朗APT34更新武

    [译] APT分析报告:09.伊朗APT34更新武

腾讯云代理商
海外云服务器