posts - 22, comments - 32, trackbacks - 0, articles - 71
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
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对象,看个人喜好选择。

只有注册用户登录后才能发表评论。


网站导航: