SpringBoot中修改proxyTargetClass,但事务代理始终为CGLIB

一、配置

在Springboot中,开启事务特别简单,如下

1.在启动类上或者配置类上增加@EnableTransactionManagement

2.在需要开启事务的方法上增加@Transactional

 

二、问题

因为本人有个特别不好的习惯,经常把@Transactional注解使用在interface的方法上,最近遇到一个问题,事务不回滚。但在排查问题时debug发现,开启事务的类是以CGLIB方式实现的代理对象,但印象中,如果不配置proxyTargetClass的话,默认应该是false,JDK的动态代理,于是找了一下原因,特此记录一下过程

 

三、查问题

  1.查看@Transactional源码,并没有代理相关配置

  2.查看@EnableTransactionManagement,存在代理相关配置,如下

/**
 * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
 * opposed to standard Java interface-based proxies ({@code false}). The default is
 * {@code false}. <strong>Applicable only if {@link #mode()} is set to
 * {@link AdviceMode#PROXY}</strong>.
 * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
 * Spring-managed beans requiring proxying, not just those marked with
 * {@code @Transactional}. For example, other beans marked with Spring's
 * {@code @Async} annotation will be upgraded to subclass proxying at the same
 * time. This approach has no negative impact in practice unless one is explicitly
 * expecting one type of proxy vs another, e.g. in tests.
 */
boolean proxyTargetClass() default false;

默认值是false,是JDK的动态代理,与记忆符合,但与实际情况不符。

  3.因为Spring的声明事务是基于AOP的,所以全文搜索AOP相关字样发现(此方法比较笨),Springboot引入的一个包spring-boot-autoconfigure,在此包下有AOP的配置,并且有proxy-target-class的配置,默认配置为true,并且还有个参数spring.aop.auto的配置,默认为true

//出自spring-boot-autoconfigure包下spring-configuration-metadata.json文件
{
  "defaultValue": true,
  "name": "spring.aop.auto",
  "description": "Add @EnableAspectJAutoProxy.",
  "type": "java.lang.Boolean"
},
{
  "defaultValue": true,
  "name": "spring.aop.proxy-target-class",
  "description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
  "type": "java.lang.Boolean"
},

  4.进行验证

application.yaml配置spring.aop.auto

application.yaml配置spring.aop.proxy-target-class

注解@EnableTransactionManagement

proxyTargetClass

代理技术

备注

true

false

false

JDK动态代理

 

true

true

false

CGLIB

默认值

true

false

true

CGLIB

 

true

true

true

CGLIB

 

false

false

false

JDK动态代理

 

false

true

false

JDK动态代理

 

false

false

true

CGLIB

 

false

true

true

CGLIB

 

 

四、总结

    当springboot开启spring.aop.auto设置为true时(类似于自动增加了@EnableAspectJAutoProxy注解),则注解配置配置文件配置有一个配置CGLIB(true),则代理使用CGLIB实现代理,否则使用JDK动态代理

    当springboot开启spring.aop.auto设置为false时,代理方式仅仅受注解配置影响。

    最后本人修改了注解位置,修改到了具体实现类的方法上。

 

五、其他说明

基于CGLIB的代理与基于JDK的动态代理实现的声明式事务的区别:

  • CGLIB基于继承实现,JDK动态代理基于实现接口实现
  • CGLIB的代理类需要事务注解@Transactional标注在类上(或方法)(此处还存在一些疑问,详见https://www.oschina.net/question/3221069_2310769);而JDK动态代理类事务注解@Transactional可以标注在接口上(或方法),也可以标注在实现类上(或方法)
  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值