SpringBoot + Shiro导致 @Transactional 事务 和 @Async 多线程 失效问题

我们使用的 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 注解也需要 懒加载 ,要不可能会失效

希望可以帮助到你!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Shiro中,判断session是否失效可以通过以下代码实现: ```java Subject subject = SecurityUtils.getSubject(); if (subject != null) { Session session = subject.getSession(false); if (session == null) { // session已经失效 } } ``` 上述代码中,首先通过`SecurityUtils.getSubject()`获取`Subject`对象,再通过`subject.getSession(false)`获取当前用户的`Session`对象,如果返回值为`null`,则表示`Session`已经失效。 当然,也可以通过在Shiro配置文件中配置`sessionManager`,设置`sessionValidationSchedulerEnabled`参数为`true`,开启Shiro的`Session`定期检查功能,实现自动检测`Session`是否失效。 另外,在Spring Boot中集成Shiro时,可以通过实现`SessionListener`接口,监听`Session`的创建、销毁和过期事件,并在事件触发时执行相应的操作。具体可参考以下代码示例: ```java @Component public class MySessionListener implements SessionListener { @Override public void onStart(Session session) { // Session创建时触发 } @Override public void onStop(Session session) { // Session销毁时触发 } @Override public void onExpiration(Session session) { // Session过期时触发 } } ``` 在以上代码中,实现了`SessionListener`接口,并在各个方法中编写相应的操作代码,以实现对`Session`的监听。最后,在Spring Boot配置文件中配置`shiro.sessionListeners`参数,将自定义的`SessionListener`注册到Shiro中即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值