文章目录
- 事务
- 理论执行过程
- @EnableTransactionManagement
- 底层实现
事务
在线流程图
理论执行过程
通过事务管理器创建一个连接对象connection1
设置事务隔离级别、是否只读等
conn1.autocommit(false)
将conn1存入ThreadLocal中Map<DataSource,Connection>
执行目标方法、多条sql:target.method()
挂起 ---> con1
通过事务管理器创建一个连接对象connection2
设置事务隔离级别、是否只读等
conn2.autocommit(false)
将conn2存入ThreadLocal中Map<DataSource,Connection>
执行目标方法、多条sql:target.method()
根据执行结果进行事务提交/回滚 commit()-->回滚标记true-->rollback() rollback()-->异常匹配-->commmit()
恢复 ---> con1 ---> ThreadLocal Map
根据执行结果进行事务提交/ 回滚 commit() ---> 回滚标记true ---> rollback() rollback()-->异常匹配-->commmit()
@EnableTransactionManagement
@EnableTransactionManagement内,其实就是导入了一个TransactionManagementConfigurationSelector
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
...
}
而在TransactionManagementConfigurationSelector
类它其实是一个ImportSelector
类型的,在该类的selectImports()
方法中主要就是导入了两个类
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
// 默认是PROXY,这里会往Spring容器中导入两个类
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
// 表示不用动态代理技术,用ASPECTJ技术,比较麻烦了
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
-
AutoProxyRegistrar
简单理解为就是一个BeanPostProcessor,进行AOP的入口
此类会往Spring容器中添加一个
InfrastructureAdvisorAutoProxyCreator
的Bean,此类就和进行AOP操作时导入的AnnotationAwareAspectJAutoProxyCreator
类一样,他们两个类都是AbstractAutoProxyCreator
的子类,也就是说都是一个BeanPostProcessorInfrastructureAdvisorAutoProxyCreator
它不会去解析@Aspectj切面类,但是它的父类会获取Spring容器中所有的Advisor
-
ProxyTransactionManagementConfiguration
简单理解为
这个配置类使用@Bean注解往Spring容器中添加了三个bean
-
BeanFactoryTransactionAttributeSourceAdvisor
它就是一个Advisor,我们知道它是由advice+Pointcut组成。在创建该bean时,会进行依赖注入,在方法形参中注入下面两个类型的bean
-
TransactionAttributeSource
它和pointcut有关系,Pointcut会用到该类,我们可以把它简单理解为就是一个工具类,它会去解析方法上写的@Transactional注解信息
-
TransactionInterceptor
就是advice执行链,也就是Interceptor
-
总结:
-
我们要事务要使用AOP这个功能,那么就一定是需要一个BeanPostProcessor来作为启动入口,也就是
AutoProxyRegistrar
类引入的InfrastructureAdvisorAutoProxyCreator
类 -
在创建普通bean时,在实例化后会取出所有的Advisor和当前bean进行匹配。
要经过advisor中的Pointcut去进行类和方法匹配,只要是匹配上了就表示当前bean是需要创建一个代理对象的。
这里也就用上了
BeanFactoryTransactionAttributeSourceAdvisor
和TransactionAttributeSource
两个类 -
代理对象到时候执行目标方式之前,会经过Pointcut匹配,再到Interceptor链,会进行事务相关的处理,再去调用目标方法。
这里也就用上了
TransactionInterceptor
类
至此,@EnableTransactionManagement
注解的总体功能就是这样,剩下的只是各个类中的详细实现
底层实现
前置知识:
- 在创建各个bean时,会在实例化后执行BeanPostProcessor中的后置方法
- 在这个过程中会进行AOP操作,把Spring容器中所有的Advisor类型的bean找出来,并和当前正在创建的bean进行匹配
- 将匹配筛选后的Advisor集合、当前创建的bean 使用ProxyFactory创建一个代理对象。
- 当代理对象调用目标方法时,就会去遍历ProxyFactory中添加的所有Advisor,执行匹配成功的Interceptor链中的各个invoke()方法 --> proceed()方法
当我们使用Spring事务这个功能,在方法上加了@Transactional注解,并通过代理对象调用该方法时,就会最开始进入到Interceptor的invoke()方法中。也就是TransactionInterceptor.invoke(MethodInvocation invocation)
方法
最核心的代码就是下面这一段
// 下面几个关键方法就不粘贴源码了,各位小伙伴自行根据最上方流程图去跟源码
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// 如果有必要就创建事务,这里就涉及到事务传播机制的实现了
// TransactionInfo表示一个逻辑事务,比如两个逻辑事务属于同一个物理事务
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// 执行下一个Interceptor或被代理对象中的方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 抛异常了,则回滚事务,或者
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
...
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
源码中的小记录:
// Spring源码中数据库连接对象的状态转变
Connection --> ConnectionHolder --> DataSourceTransactionObject(常见)---> SuspendedResourcesHolder(挂起) --> TransactionStatus ---> TransactionInfo
Spring事务的其他操作:
@Component
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private UserService userService;
@Transactional
public void test(){
System.out.println("test()...");
jdbcTemplate.execute("insert into m_test VALUES(2,100)");
userService.a();
// 自己添加多个同步器
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void suspend() {
// 当前事务挂起时执行
TransactionSynchronization.super.suspend();
}
@Override
public void resume() {
// 当前事务恢复时执行
TransactionSynchronization.super.resume();
}
@Override
public void beforeCommit(boolean readOnly) {
// 当前事务提交前执行
TransactionSynchronization.super.beforeCommit(readOnly);
}
@Override
public void beforeCompletion() {
// 当前事务完成前执行,提交或回滚都算是事务完成
TransactionSynchronization.super.beforeCompletion();
}
@Override
public void afterCommit() {
// 当前事务提交后执行
TransactionSynchronization.super.afterCommit();
}
@Override
public void afterCompletion(int status) {
// 当前事务完成后执行
TransactionSynchronization.super.afterCompletion(status);
}
});
// 捕捉一个异常,使用一个自定义的数据友好返回前端,但是该方法前面执行的sql还是需要回滚
try {
throw new NullPointerException();
} catch (NullPointerException e) {
// 事务提交时会判断RollbackOnly,再不提交转而进行回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return new Result();
}
}
@Transactional()
public void a(){
System.out.println("a()...");
jdbcTemplate.execute("insert into m_test VALUES(3,300)");
}
}