在对数据库进行操作时,有时候会把多个操作放到一个事务里,保证原子性,那么这个事务是怎么实现的呢?
下面我们先通过一个demo看一下事务的使用:
一:事务的使用
数据库jdbc配置:
java;gutter:true;</p>
<h2>数据源配置</h2>
<p>jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/study
jdbc.username=root
jdbc.password=root</p>
<pre><code>
spring-context.xml配置:
写一个类,方法上加上@Transactional注解
;gutter:true;
@Service
public class TestTransactionalService {
@Autowired
private UserMapper userMapper;
@Transactional
public int add(){
User user = new User();
user.setName("Lucy");
user.setAge("30");
int effectCount = userMapper.insert(user);
System.out.println("影响条数: "+effectCount);
int i = 10/0;
return effectCount;
}
}
测试代码:
二:事务的原理分析
1:注册埋点,注册BeanDefinition对象,实例化BeanPostProcessor对象,并注册到beanPostProcessors中
配置开启事务管理:
通过命名空间找到对象的handler类:
注册自定义标签tx的属性解析器,AnnotationDrivenBeanDefinitionParser
AutoProxyCreator已经以BeanDefinition的形式注册到了BeanDefinitionMaps中。
注册其他类:
2:实例化并注册到beanPostProcessors中
是在refresh方法的registryBeanPostProcessor中实现的,这里不再赘述
3:寻找增强,创建代理
用增强去匹配当前bean信息:
创建代理:
4:拦截方法,对方法进行增强
TestTransactionalService这个对象已经被代理
进入DynamicAdvisedInterceptor类的intercept方法:
只有一个增强:
TransactionInterceptor 的 invoke方法
抛出异常,进入catch代码块:
回滚事务:
DataSourceTransactionManager类的doRollback回滚方法:
可以看出正在执行回滚操作是在DataSourceTransactionManager类中进行的
下面把导致异常的代码去掉,看一下提交的情况:
提交事务:
调到了DataSourceTransactionManager的doCommit事务:
到这里事务管理的分析就结束了,实现原理就是对数据库的操作方法进行增强,如果执行成功就commit,执行失败就rollback。
a: 看一下异常回滚里面小细节:rollbackFor ,什么异常才回滚?
如果@Transactional注解上不配置rollbackFor 默认是RuntimException 或者 Error
如果自定义rollbackFor类型:
b:如果@Transactional注释的方法不是public修饰的,也不会被代理,找不到@Transactional注解的信息
c:如果是内部调用,会不会生效,从其他类调用add方法:
调用add方法,进入intercept
在add方法中调用addData,实际是调用target的方法,不是代理方法,所以不会有事务的存在
Original: https://www.cnblogs.com/warrior4236/p/13257450.html
Author: warrior1234
Title: spring源码分析——事务的实现原理
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/541596/
转载文章受原作者版权保护。转载请注明原作者出处!