Spring事务调用类自己方法失效解决办法和原因
问题
正常情况下,我们都是在controller里调用service里的方法,这个方法如果需要加事务,就在方法上加上@Transactional,这样是没问题的,事务会生效。
可是如果像下面这样,绕以下,service里方法调用了自己类的方法,这个时候即使加了@Transactional,事务也不会生效。
@Controller
public class TestController { @Autowired
private TestService testService; @GetMapping("/test")
public void test(){
testService.methodB();
} }
@Service
public class TestService { @Transactional
public void methodA(){ } /**
* 这里调用methodA() 的事务将会失效
*/
public void methodB(){
this.methodA();
} }
原因
因为,spring的事务实现是使用了代理类来实现,而这里的this.methodA(),并没有走TestService的代理类,所以事务会失效。
解决
方法1:把methodA()和methodB()分别放到不同的类里。
方法2:自己注入自己,用注入的实例调用
@Service
public class TestService { @Autowired
private TestService testService; @Transactional
public void methodA(){ } /**
* 这里调用methodA() 的事务将会生效
*/
public void methodB(){
testService.methodA();
} }
方法3:获取代理类,利用代理类调用自己类的方法
@Service
public class TestService { @Transactional
public void methodA(){ } /**
* 这里调用methodA() 的事务将会生效
*/
public void methodB(){
((TestService)AopContext.currentProxy()).methodA();
} }
最后
spring的aop代理有jdk代理和cglib代理实现,具体参阅java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总
//是否代理对象
AopUtils.isAopProxy(AopContext.currentProxy()); //是否cglib 代理对象
AopUtils.isCglibProxy(AopContext.currentProxy()); //是否jdk动态代理
AopUtils.isJdkDynamicProxy(AopContext.currentProxy());
Spring事务调用类自己方法失效解决办法和原因的更多相关文章
- iOS:didSelectRowAtIndexPath:方法失效解决办法
问题描述及解决过程: 为了达到点击TableView空白区退出键盘的效果,给控制器注册了一个UITapGestureRecognizer来识别点击事件,代码如下: #pragma mark - 设置手 ...
- C++ 11 线程调用类的成员函数解决办法
在C++中,_beginthreadex 创建线程是很麻烦的.要求入口函数必须是类的静态函数. 通常,可以采用thunk,或者模板来实现. 因C++ 11中引入了 std::async ,可以很好的解 ...
- 一个页面上调用多个setInterval失效解决办法(使用于同一时间间隔)
将方法封装在一起,只调用一个setInterval window.setInterval( function () { $.ajax({ type: "GET", url: '/M ...
- Android开发教程 - 使用Data Binding Android Studio不能正常生成相关类/方法的解决办法
本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...
- Java动态调用类中方法
在Java中,调用类的方法有两种方式:对于静态方法可以直接使用类名调用,对于非静态方法必须使用类的对象调用.反射机制提供了比较另类的调用方式,可以根据需要指定要调用的方法,而不必在编程时确定.调用的方 ...
- C#通过反射调用类及方法
反射有个典型的应用,就是菜单的动态加载,原理就是通过反射调用某个窗体(类).下面演示一下通过反射调用类及方法: 1.新建一个类,命名为:ReflectionHelper,代码如下: #region 创 ...
- 基于Spring框架的简单多数据源切换解决办法
基于Spring框架的简单多数据源切换解决办法 Spring框架JDBC包提供了一个抽象类AbstractRoutingDataSource提供了动态切换数据库的基础方法.我们仅仅需要实现一个简单的数 ...
- Xcode升级插件失效解决办法-升级版
Xcode升级插件失效解决办法 每每升级Xcode,第三方插件总是中枪.解决办法也基本是依据http://joeshang.github.io/2015/04/10/fix-xcode-upgrade ...
- MySQL ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) 的解决办法和原因
这两天下载了MySQL5.7.11进行安装,发现到了初次使用输入密码的时候,不管怎样都进不去,即使按照网上说的在mysqld 下面添加skip-grant-tables也是不行,后来研究了两天,终于找 ...
随机推荐
- 何谓SQLSERVER参数嗅探(转载)
大家听到“嗅探”这个词应该会觉得跟黑客肯定有关系吧,使用工具嗅探一下参数,然后截获,脱裤o(∩_∩)o .事实上,我觉得大家太敏感了,其实这篇文章跟数据库安全没有什么关系,实际上跟数据库性能调优有关相 ...
- 【设计模式】Singleton
前言 Singleton设计模式,确保全局只存在一个该类的实例.将构造器声明为private,防止调用(虽然还是可以使用反射来调用).声明一个静态的类实例在类中,声明一个公共的获取实例的方法.这篇博文 ...
- Vue中iframe和组件的通信
最近的项目开发中用到了Vue组件中嵌套iframe,相应的碰到了组件和HTML的通信问题,场景如下:demo.vue中嵌入 test.html 由于一般的iframe嵌套是用于HTML文件的,在vue ...
- Redis入门学习(一):简介
Redis是一个开源的.高性能的.基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同场景下的缓存与存储需求.同时Redis的诸多高层级功能使其可以胜任消息队列.任务队列等不同的角色. 20 ...
- Eclipse 笔记
2004年前的开发架构:(操作系统+数据库+中间件+开发工具) AIX + DB2 + WAS + WSAD === 皇家级 UNIX/Linux + Oracle +BEA WebLogic + ...
- 使用 Docker Alpine 镜像安装 nginx
微镜像Alpine,Alpine Linux 是一款独立的⾮商业性的通⽤ Linux 发行版,Alpine Linux 围绕 musl libc 和 busybox 构建,尽管体积很小,Apline ...
- linux 使用indent格式化代码
indent是一个代码整理工具,能够方便快速的将代码格式化. 这是我较习惯的代码风格,网上还有很多其他的 参数: -nbad -bap -bbo -nbc -br -brs -c33 -cd33 -n ...
- GCC 预处理,汇编,编译,链接,连接静态库,动态库
gcc Record gcc -E file1.c > output gcc -E file1.c -o file1.i gcc -S file1.i -o file1.s gcc -S fil ...
- logrotate日志管理工具与split文件切割命令
概述 logrotate是一个Linux系统默认安装了的日志文件管理工具,用来把旧文件轮转.压缩.删除,并且创建新的日志文件.我们可以根据日志文件的大小.天数等来转储,便于对日志文件管理. logro ...
- opencv局限:cv::FileStorage读取中,xml文件的第一层节点不能超过4个
今天测试发现一个问题,cv::FileStorage读取中,xml文件的第一层节点不能超过4个. <?xml version="1.0"?> <opencv_st ...