Spring service本类中方法互相调用事物失效问题

摘要:
关于Spring,AOP用于处理事务,CGLIB代理用于动态代理。因此,只要您了解Spring的AOP实现,就会知道为什么此类服务中方法的相互调用会导致*$$EnhancerBySpringCGLIB$$2364c0b7代理**/@Testpublicvoid testTransactionalPropagation(){log.info;springTransactionSqlserverServiceImpl.moneyTestOne();}在运行前后,可以得出moneyTestTwo方法不起作用的结论。要使其正常工作,只需要向moneyTestOne方法添加一个事务注释。Spring使用AopProxy接口来抽象这两个实现,并实现一致的AOP方法。现在看来,这个抽象也有一个缺陷,那就是消除了Cglib直接创建普通类的增强子类的能力。

简介

Spring事物利用的是AOP,动态代理采用CGLIB代理(默认,也可以用Proxy代理,但是Proxy代理效率低于CGLIB代理)。故只要弄懂Spring的AOP实现,就知道为什么service本类中方法互相调用会导致事物失效。

失效案例

service层代码

 public void  moneyTestOne(){
        //1.查询病人基本信息
        List<TBICXX> tbicxx = basisDao.getTBICXX();
        //2.根据CMZH更新TBMZFYHZ
        Integer TBMZFYHZCount = tbmzfyhzDao.updateByCMZH("王五", "1903003643");
        log.info("更新TBMZFYHZ影响行数{}",TBMZFYHZCount);
        this.moneyTestTwo();

    }

    @Transactional(rollbackFor = Exception.class,propagation=Propagation.REQUIRED)
    public void  moneyTestTwo(){
        //3.根据CMZH更新TBMZFYMXGH
        Integer integer = tbmzfymxghDao.updateByCMZH("王五", "2107000224");
        log.info("更新TBMZFYMXGH影响行数{}",integer);
        int i=2/0;
    }

Test层代码

/**
     * 测试其AOP事物(CGLIB代理):
     *   如moneyTestOne不添加事物,则moneyTestTwo事物及其一切传播行为将失效,这是由于spring的AOP的Cglib代理造成
     *   同理: moneyTestOne添加事物,moneyTestTwo事物及其一切传播行为也将失效,moneyTestTwo运行在moneyTestOne事物中。
     *   $$EnhancerBySpringCGLIB$$2364c0b7 代理
     **/
    @Test
    public void testTransationalPropagation(){
        log.info("测试开始,代理类{}",springTransactionSqlserverServiceImpl.getClass());
        springTransactionSqlserverServiceImpl.moneyTestOne();
    }

运行前
image
运行后
image
结论
moneyTestTwo方法事物并不生效,要想事物生效,只需要在moneyTestOne方法上加上事物注解(此方法同理会导致moneyTestTwo方法传播行为失效),

失效分析

Spring通过AopProxy接口,抽象了这两种实现,实现了一致的AOP方式:
image
现在看来,这种抽象同样带了一个缺陷,那就是抹杀了Cglib能够直接创建普通类的增强子类的能力。下图显示了Spring的AOP代理类的实际调用过程:
image

解决办法

事物声明避免在一个类中互相调用,即moneyTestOne和moneyTestTwo要么都使用事物,要么直接分成两个类。

Gitee代码地址

https://gitee.com/zhuayng/foundation-study/tree/develop/SpringBootDemo/src/main/java/com/yxkj/springbootdemo/service/impl

免责声明:文章转载自《Spring service本类中方法互相调用事物失效问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇关于linux免密登录的配置及ssh客户端基于私钥文件的登录Android Studio安装虚拟机步骤下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

spring5 源码深度解析----- AOP代理的生成

在获取了所有对应bean的增强后,便可以进行代理的创建了。回到AbstractAutoProxyCreator的wrapIfNecessary方法中,如下所示: 1 protected static final Object[] DO_NOT_PROXY = null; 2 3 protectedObject wrapIfNecessary(Obje...

设计模式之动态代理

在了解什么是动态代理模式,以及怎么实现动态代理模式之前,我们先明确一个场景,那就是当我们需要对一类实现类增加一些额外处理对其中的某些方法做一些增强时。譬如增加日志打印,参数校验,鉴权等。这些功能很重要,但是又具有一定的独立性(与业务代码不相关)。针对这种情况, 我们就可以采用动态代理模式来实现。 动态代理顾名思义,就是动态的对方法实现代理。要真正理解动态代...

Java 面向切面编程(Aspect Oriented Programming,AOP)

本文内容 实例 引入 原始方法 装饰者模式 JDK 动态代理和 cglib 代理 直接使用 AOP 框架——AspectWerkz 最近跳槽了,新公司使用了 AOP 相关的技术,于是查点资料,复习一下。之前,多少知道点,但没怎么在实际项目中使用过~ 下载 demo 实例 引入 package com.cap.aop;   publi...

Spring源码分析-SpringAop什么时候调用jdk动态代理?什么时候调用cglib

1.导入log4j.jar,开启log4j DEBUG模式 2.查看打印日志,可以发现一个重要信息: 2020-03-03 15:13:31,870 DEBUG [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator] - Creating imp...

技术问答集录(四)(spring aop Lombok 原理)

问题: Spring AOP和Lombok是什么原理? 如何实现一个自定义的Spring Boot Starter? 1.Spring AOP和Lombok是什么原理? Spring AOP原理 ①AOP: AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提...

Spring强制使用CGLIB代理事务

 Spring强制使用CGLIB代理事务   springaopjdkreferenceclasspath Spring1.2: 将事务代理工厂[TransactionProxyFactoryBean] 或 自动代理拦截器[BeanNameAutoProxyCreator] 的 proxyTargetClass 属性,设置为true,则使用CG...