一個項目中,避免不了使用事務,而在Springboot項目中,我們一般使用@Transactional注解來設置事務控制,@Transactional的詳情使用可見博客https://www.cnblogs.com/pengpengdeyuan/p/12737891.html。
在加完@Transactional注解啟動項目時,可能會出現以下報錯
Description:
The bean 'testService' could not be injected as a 'com.xxx.xxx.service.impl.TestService' because it is a JDK dynamic proxy that implements: com.pk.kxl.service.ITestService Action: Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.
這類情況主要是jdk自動代理與CGlib代理的注入方式差異造成的。
一、查看是否開啟事務支持
首先查看項目是否是SpringBoot項目,SpringBoot項目會自動開啟事務支持。
二、查看注入方式
從錯誤信息中可以看出,它是在我的Controller層中,注入testService這個Bean時失敗,(失敗的原因就是我導入的是接口實現,而springboot的事務默認是使用jdk的動態代理,是基於接口進行注入的)。意思就是我注入的是service層的實現類,這種操作是非法的,改成注入service層接口就可以解決。
這時可以想到,既然jdk動態代理不行,那我們就改成CGlib動態代理(基於類,即設置proxyTargetClass=True在啟動事務管理上、、、@EnableTransactionManagement(proxyTargetClass=True)),此時需要引入相應的cglib庫的jar包,在springboot中已經集成了。但在spring3.2之前是需要引入的。
@SpringBootApplication //啟用事務管理(可省略) @EnableTransactionManagement(proxyTargetClass=True)
第三種方式就可以使用@Scop注解去解決,他會將所有方法上的事務都強制改為是CGLib方式代理的。
方法:在service層上添加一個注解 @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Service @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED) @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)