【Spring】——非事务方法访问事务方法

背景简单介绍

在Spring开发中,为了使得业务的顺利开发,我们免不了需要使用事务,而在使用时,应该注意下面这一点

内容讲解

在Spring框架中,我们不能通过非事务方法去调用事务方法

代码演示
/**
 * 这个类中进行测试方法的调用
 */
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    public void testTransactionMethod() {
        try {
            transactionMethod();
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    @Override
    public void addUser() {
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = RuntimeException.class)
    public void transactionMethod() {
        try {
            userMapper.insert(new User());
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}

编写一个测试类,进行我们定义方法的测试

public class UserServiceImplTest {

    @Test
    void testTransactionMethod() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.testTransactionMethod();
    }
} 

代码执行结果

java.lang.RuntimeException
	at com.service.impl.UserServiceImpl.testTransactionMethod(UserServiceImpl.java:20)
	at com.service.impl.UserServiceImplTest.testTransactionMethod(UserServiceImplTest.java:12)

那么可以发现,我们的方法调用报错了,那么接下类我们就来分析下这到底是咋回事?

原理说明

在Spring中,我们对于事务传播的控制在TransactionDefinition这个类中

    int PROPAGATION_REQUIRED = 0; // 支持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就新建一个事务
    int PROPAGATION_SUPPORTS = 1; // 持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就以非事务的方式执行;
    int PROPAGATION_MANDATORY = 2; // 支持当前事务,如果有就加入当前事务中;如果当前没有事务,就抛出异常;
    int PROPAGATION_REQUIRES_NEW = 3; // 新建事务,如果当前存在事务,就把当前事务挂起;如果当前方法没有事务,就新建事务;
    int PROPAGATION_NOT_SUPPORTED = 4; // 以非事务方式执行,如果当前方法存在事务就挂起当前事务;如果当前方法不存在事务,就以非事务方式执行;
    int PROPAGATION_NEVER = 5; // 以非事务方式执行,如果当前方法存在事务就抛出异常;如果当前方法不存在事务,就以非事务方式执行;
    int PROPAGATION_NESTED = 6; // 如果当前方法有事务,则在嵌套事务内执行;如果当前方法没有事务,则与required操作类似;
    
	// 下面是Spring事务对应的几种隔离级别,具体可以参考Mysql中的隔离级别
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

    default int getPropagationBehavior() {
        return 0;
    }

    default int getIsolationLevel() {
        return -1;
    }

    default int getTimeout() {
        return -1;
    }

    default boolean isReadOnly() {
        return false;
    }
  • 我们知道在Spring框架中,是基于xml配置文件进行各种技术的实现的,事务也不例外,在事务配置文件中,我们通过<tx:annotation-driven为开头的配置来开启事务的相关定义。而该标签在Spring中,会通过Spring中的AnnotationDrivenBeanDefinitionParser类的parse()方法进行解析,具体实现解析过程,大家可以进行源码阅读学习,这里不再说明。
  • 而对于Spring的Bean加载中,Spring会进行检测加载的该bean中方法上是否有@Transaction注解,如果有的话,Spring会给该bean创建一个子类代理类,当别处进行调用该bean下的注解方法时,Spring默认会使用该代理类进行方法调用,而在该bean中的方法进行注解方法内部调用时,就不会产生代理类,也就会出现注解失效的问题。

注解失效了,怎么办???

解决方案

一、将事务方法专门抽取出来放到一个类中进行统一管理;
二、获取本对象的代理对象,再通过该代理对象进行方法调用,使用该功能,需要在配置文件中开启一下注解<aop:aspectj-autoproxy expose-proxy="true"/>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值