Posted on 2017-06-20 17:03
為自己代言 閱讀(1956)
評論(0) 編輯 收藏 所屬分類:
spring cloud 微服務
1: Java注解@Transactional事務類內調用不生效問題及解決辦法
在 Spring 的 AOP 代理下,只有目標方法由外部調用,目標方法才由 Spring 生成的代理對象來管理,這會造成自調用問題。
若同一類中的其他沒有@Transactional 注解的方法內部調用有@Transactional 注解的方法,有@Transactional 注解的方法的事務被忽略,不會發生回滾
2:場景問題:
比如:一個class A類 中有三個方法 a(),b(),c(),d()
@Transactional
a();
@Transactional
b();
@Transactional
c(){
this.a();
this.b();
}
如果同一個類中:
@Transactional
d(){
this.c();
}
這樣d() @Transactional 會失效,如果出現異常,事物不會回滾,原因是 @Transactional 使用了spring proxy 代理對象 會被AOP攔截,
this.c(),這樣調用是本地對象調用,細心同學發現只有 最外層使用代理對象就可以使 @Transactional生效。
解決方法:
1:最簡單的一種在自己實現類中注入自己 例:
@Autowired
private Class class;
這樣就可以走spring IOC 容器,出來就是proxy 對象;
2:第二咱方式是通過AopContext.currentProxy()方式
增加maven依賴:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency> 如果存在忽略這個
如果是springboot工程在main 方法上增加 @EnableAspectJAutoProxy(exposeProxy = true,proxyTargetClass = true)
例:
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true,proxyTargetClass = true)
public class CommonComponentStartApplication {
public static void main(String[] args) {
SpringApplication.run(CommonComponentStartApplication.class, args);
}
}
然后就可以在上面的例子中d()中這樣使用:
@Transactional
d(){
Class class= ((Class)AopContext.currentProxy());
class.c();
}
3:第三種 是通過 applicationcontext 獲取 bean
總之這幾種方法都是為了得到spring proxy對象,看個人喜好選擇。