問題
正常情況下,我們都是在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());