赞
踩
在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"/>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。