文章目录
- 事务
- 理论执行过程
- @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 {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate UserService userService;@Transactionalpublic void test(){System.out.println("test()...");jdbcTemplate.execute("insert into m_test VALUES(2,100)");userService.a();// 自己添加多个同步器TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void suspend() {// 当前事务挂起时执行TransactionSynchronization.super.suspend();}@Overridepublic void resume() {// 当前事务恢复时执行TransactionSynchronization.super.resume();}@Overridepublic void beforeCommit(boolean readOnly) {// 当前事务提交前执行TransactionSynchronization.super.beforeCommit(readOnly);}@Overridepublic void beforeCompletion() {// 当前事务完成前执行,提交或回滚都算是事务完成TransactionSynchronization.super.beforeCompletion();}@Overridepublic void afterCommit() {// 当前事务提交后执行TransactionSynchronization.super.afterCommit();}@Overridepublic 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)");}}