Posted on 2017-06-20 17:03
为自己代言 阅读(1943)
评论(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对象,看个人喜好选择。