1. 目录 [TOC]
2. 说明 @Transactional
为spring提供的申明式事务管理,开发者可以很快速的开启事务,同时,其自带了事务管理,可以在事务结束时自行提交或回滚,大大减少了程序编码,同时也避免了IO连接泄露 同时,@Transactional
还提供了传播特性和隔离级别,更好的扩展了程序中可能出现的场景
3. 依赖分析 4. 源码分析 4.1. 自动配置事务管理器 spring项目中需要在xml文件中配置事务管理器,而springboot中通过@EnableTransactionManagement
来开启事务生效,新版本中已经不需要@EnableTransactionManagement
了,直接通过TransactionAutoConfiguration
类来进行自动配置,注入需要的类。
4.1.1. 加载TransactionAutoConfiguration
springboot自动化配置会扫描配置的configuration
,加载主要为spring boot的相关流程逻辑。 其扫描先不做分析,从ConfigurationClassParser$DeferredImportSelectorGroupingHandler
分析加载,此类就是扫描自动配置类的,其中groupings 属性保存了所有的配置类的信息,如图
比如我们常见的org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
、org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
、org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
、org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
、org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
、org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
等 我们今天分析的TransactionAutoConfiguration
也在其中 首先我们看processGroupImports()
方法,会将每一个配置configuration进行processImports()
处理,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class ConfigurationClassParser$DeferredImportSelectorGroupingHandler { public void processGroupImports () { for (DeferredImportSelectorGrouping grouping : this .groupings.values()) { Predicate<String> exclusionFilter = grouping.getCandidateFilter(); grouping.getImports().forEach(entry -> { ConfigurationClass configurationClass = this .configurationClasses.get(entry.getMetadata()); try { processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter), Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)), exclusionFilter, false ); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException ( "Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]" , ex); } }); } } }
processImports()
处理如下,此方法很长,且好些看不懂,我们看主要的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class ConfigurationClassParser$DeferredImportSelectorGroupingHandler { private void processImports (ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) { if (checkForCircularImports && isChainedImportOnStack(configClass)) { } else { this .importStack.push(configClass); try { for (SourceClass candidate : importCandidates) { if (candidate.isAssignable(ImportSelector.class)) { if (selector instanceof DeferredImportSelector) { this .deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); } else { String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false ); } } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { this .importStack.registerImport( currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter); } } } catch Exception ex) { throw ex; } finally { this .importStack.pop(); } } } }
this.importStack.registerImport
主要将org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration.class
的配置类和内部类的配置类加载进来
processConfigurationClass()
处理配置类
1 2 3 4 5 6 7 8 9 10 11 12 class ConfigurationClassParser$DeferredImportSelectorGroupingHandler { protected void processConfigurationClass (ConfigurationClass configClass, Predicate<String> filter) throws IOException { do { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null ); this .configurationClasses.put(configClass, configClass); } }
doProcessConfigurationClass()
执行处理配置 此类为处理的主要类了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class ConfigurationClassParser$DeferredImportSelectorGroupingHandler { protected final SourceClass doProcessConfigurationClass ( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { if (configClass.getMetadata().isAnnotated(Component.class.getName())) { processMemberClasses(configClass, sourceClass, filter); } for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { } processImports(configClass, sourceClass, getImports(sourceClass), filter, true ); AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null ) { String[] resources = importResource.getStringArray("locations" ); Class<? extends BeanDefinitionReader > readerClass = importResource.getClass("reader" ); for (String resource : resources) { String resolvedResource = this .environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod (methodMetadata, configClass)); } processInterfaces(configClass, sourceClass); if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith("java" ) && !this .knownSuperclasses.containsKey(superclass)) { this .knownSuperclasses.put(superclass, configClass); return sourceClass.getSuperClass(); } } return null ; } }
加载如图
具体的关于TransactionAutoConfiguration
见后文
加载完成后在外层将获取到的信息加入到ConfigurationClassParser.configurationClasses 中this.configurationClasses.put(configClass, configClass)
4.1.2. TransactionAutoConfiguration
自动配置类 由前面分析我们已经得到了springboot加载到配置类TransactionAutoConfiguration
,本小结主要分析配置类的配置
4.1.2.1. 配置类TransactionAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 @Configuration(proxyBeanMethods = false) @ConditionalOnClass(PlatformTransactionManager.class) @AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class }) @EnableConfigurationProperties(TransactionProperties.class) public class TransactionAutoConfiguration { @Bean @ConditionalOnMissingBean public TransactionManagerCustomizers platformTransactionManagerCustomizers ( ObjectProvider<PlatformTransactionManagerCustomizer<?>> customizers) { return new TransactionManagerCustomizers (customizers.orderedStream().collect(Collectors.toList())); } @Bean @ConditionalOnMissingBean @ConditionalOnSingleCandidate(ReactiveTransactionManager.class) public TransactionalOperator transactionalOperator (ReactiveTransactionManager transactionManager) { return TransactionalOperator.create(transactionManager); } @Configuration(proxyBeanMethods = false) @ConditionalOnSingleCandidate(PlatformTransactionManager.class) public static class TransactionTemplateConfiguration { @Bean @ConditionalOnMissingBean(TransactionOperations.class) public TransactionTemplate transactionTemplate (PlatformTransactionManager transactionManager) { return new TransactionTemplate (transactionManager); } } @Configuration(proxyBeanMethods = false) @ConditionalOnBean(TransactionManager.class) @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class) public static class EnableTransactionManagementConfiguration { @Configuration(proxyBeanMethods = false) @EnableTransactionManagement(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) public static class JdkDynamicAutoProxyConfiguration { } @Configuration(proxyBeanMethods = false) @EnableTransactionManagement(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { } } }
4.1.2.2. 配置类@EnableTransactionManagement
前面我们已经知道会加载到@EnableTransactionManagement,并且会选择JDK 或CGLIB 其中一个做代理 接下来我们继续分析@EnableTransactionManagement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement { boolean proxyTargetClass () default false ; AdviceMode mode () default AdviceMode.PROXY; int order () default Ordered.LOWEST_PRECEDENCE; }
以上是一个全局配置,一般不用配默认就是此种,要配置的话根据spring.aop
相关配置属性定义
4.1.2.2.1. TransactionManagementConfigurationSelector
选择配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector <EnableTransactionManagement> { public final String[] selectImports(AnnotationMetadata importingClassMetadata) { Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class); Assert.state(annType != null , "Unresolvable type argument for AdviceModeImportSelector" ); AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType); if (attributes == null ) { throw new IllegalArgumentException (String.format( "@%s is not present on importing class '%s' as expected" , annType.getSimpleName(), importingClassMetadata.getClassName())); } AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName()); String[] imports = selectImports(adviceMode); if (imports == null ) { throw new IllegalArgumentException ("Unknown AdviceMode: " + adviceMode); } return imports; } @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String [] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String [] {determineTransactionAspectClass()}; default : return null ; } } private String determineTransactionAspectClass () { return (ClassUtils.isPresent("javax.transaction.Transactional" , getClass().getClassLoader()) ? TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME : TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME); } }
此类主要将需要配置的额外的初始化类配置类ProxyTransactionManagementConfiguration
获取到importStack
中,后续初始化配置此类,
4.1.2.3. ProxyTransactionManagementConfiguration
动态代理配置类 此类配置了TransactionInterceptor
事务拦截器和TransactionAttributeSource
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @Configuration(proxyBeanMethods = false) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor ( TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor (); advisor.setTransactionAttributeSource(transactionAttributeSource); advisor.setAdvice(transactionInterceptor); if (this .enableTx != null ) { advisor.setOrder(this .enableTx.<Integer>getNumber("order" )); } return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource () { return new AnnotationTransactionAttributeSource (); } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor (TransactionAttributeSource transactionAttributeSource) { TransactionInterceptor interceptor = new TransactionInterceptor (); interceptor.setTransactionAttributeSource(transactionAttributeSource); if (this .txManager != null ) { interceptor.setTransactionManager(this .txManager); } return interceptor; } }
TransactionInterceptor
事务拦截器,被代理的@Transactional
都会加载动态代理,就会经过此拦截器,也就是其实他是具体处理事务的。TransactionAttributeSource
则为处理注解属性相关的类,保存了初始化的事务的传播特性、隔离级别、回滚等,这里更像一个Map容器,主要属性在其内部的TransactionAttribute
上
4.2. 应用使用 我们知道,加了@Transactional
的实际上在spring的容器中已经是代理过后的bean了,那么从注入的地方调用代码实际上首先会进入到代理类CglibAopProxy$DynamicAdvisedInterceptor
1 2 3 4 5 6 7 8 @Autowired UucsUserService uucsUserService; @Test public void t3 () { UucsUser user = uucsUserService.getUser(1 ); }
调用进入代理对象DynamicAdvisedInterceptor
的intercept()
方法
看一下进入时proxy
可以发现此动态代理是多层代理,这也符合实际情况,我们只关注DynamicAdvisedInterceptor
本身的流程即可,处理到其他的代理时无需再关注 再看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class CglibAopProxy$DynamicAdvisedInterceptor { @Override @Nullable public Object intercept (Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null ; boolean setProxyContext = false ; Object target = null ; TargetSource targetSource = this .advised.getTargetSource(); try { if (this .advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true ; } target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null ); List<Object> chain = this .advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { retVal = new CglibMethodInvocation (proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } } }
<1> 其中CglibMethodInvocation.proceed()是典型的代理的代码,代理相关可以直接跳过,在方法中得到实际的处理类TransactionInterceptor
,再执行反射((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)
调用进入TransactionInterceptor#invoke()
方法
4.2.1. TransactionInterceptor
事务拦截器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 public class TransactionInterceptor { public Object invoke (MethodInvocation invocation) throws Throwable { Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null ); return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); } protected Object invokeWithinTransaction (Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { TransactionAttributeSource tas = getTransactionAttributeSource(); final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null ); final TransactionManager tm = determineTransactionManager(txAttr); if (this .reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) { } PlatformTransactionManager ptm = asPlatformTransactionManager(tm); final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) { TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification); Object retVal; try { retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) { TransactionStatus status = txInfo.getTransactionStatus(); if (status != null && txAttr != null ) { retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status); } } commitTransactionAfterReturning(txInfo); return retVal; } else { } } }
<1> TransactionInfo
内容,保存到有事务的特性等
4.2.1.1. createTransactionIfNecessary()
这里是真正开启事务的地方,为啥是ifNecessary ,因为根据传播特性可能不需要开事务的 同时这里已经把数据库连接维护好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class TransactionInterceptor { protected TransactionInfo createTransactionIfNecessary (@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) { if (txAttr != null && txAttr.getName() == null ) { txAttr = new DelegatingTransactionAttribute (txAttr) { @Override public String getName () { return joinpointIdentification; } }; } TransactionStatus status = null ; if (txAttr != null ) { if (tm != null ) { status = tm.getTransaction(txAttr); } else { if (logger.isDebugEnabled()) { logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured" ); } } } return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); } }
4.2.1.1.1. tm.getTranscation()
开启数据库连接 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 public class DataSourceTransactionManager { public final TransactionStatus getTransaction (@Nullable TransactionDefinition definition) throws TransactionException { TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults()); Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); if (isExistingTransaction(transaction)) { return handleExistingTransaction(def, transaction, debugEnabled); } if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException ("Invalid transaction timeout" , def.getTimeout()); } if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException ( "No existing transaction found for transaction marked with propagation 'mandatory'" ); } else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources = suspend(null ); try { return startTransaction(def, transaction, debugEnabled, suspendedResources); } catch (RuntimeException | Error ex) { resume(null , suspendedResources); throw ex; } } else { } } private TransactionStatus startTransaction (TransactionDefinition definition, Object transaction, boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true , newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } @Override protected void doBegin (Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null ; try { if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { Connection newCon = obtainDataSource().getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction" ); } txObject.setConnectionHolder(new ConnectionHolder (newCon), true ); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true ); con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); txObject.setReadOnly(definition.isReadOnly()); if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true ); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit" ); } con.setAutoCommit(false ); } prepareTransactionalConnection(con, definition); txObject.getConnectionHolder().setTransactionActive(true ); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { if (txObject.isNewConnectionHolder()) { DataSourceUtils.releaseConnection(con, obtainDataSource()); txObject.setConnectionHolder(null , false ); } throw new CannotCreateTransactionException ("Could not open JDBC Connection for transaction" , ex); } } protected void prepareSynchronization (DefaultTransactionStatus status, TransactionDefinition definition) { if (status.isNewSynchronization()) { TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction()); TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ? definition.getIsolationLevel() : null ); TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); TransactionSynchronizationManager.initSynchronization(); } } }
4.2.1.1.2. prepareTransactionInfo()
准备事务信息 注意到这里实际上已经开了数据库连接了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class TransactionInterceptor { protected TransactionInfo prepareTransactionInfo (@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, String joinpointIdentification, @Nullable TransactionStatus status) { TransactionInfo txInfo = new TransactionInfo (tm, txAttr, joinpointIdentification); if (txAttr != null ) { txInfo.newTransactionStatus(status); } txInfo.bindToThread(); return txInfo; } }
4.2.1.2. commitTransactionAfterReturning()
提交事务 1 2 3 4 5 6 7 8 9 10 11 public class TransactionInterceptor { protected void commitTransactionAfterReturning (@Nullable TransactionInfo txInfo) { if (txInfo != null && txInfo.getTransactionStatus() != null ) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]" ); } txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } } }
4.2.1.2.1. DatasourceTransactionManagement#commit()
提交事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 public class DatasourceTransactionManagement { @Override public final void commit (TransactionStatus status) throws TransactionException { if (status.isCompleted()) { throw new IllegalTransactionStateException ( "Transaction is already completed - do not call commit or rollback more than once per transaction" ); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; if (defStatus.isLocalRollbackOnly()) { processRollback(defStatus, false ); return ; } if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Global transaction is marked as rollback-only but transactional code requested commit" ); } processRollback(defStatus, true ); return ; } processCommit(defStatus); } private void processCommit (DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false ; try { boolean unexpectedRollback = false ; prepareForCommit(status); triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true ; if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint" ); } unexpectedRollback = status.isGlobalRollbackOnly(); status.releaseHeldSavepoint(); } else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction commit" ); } unexpectedRollback = status.isGlobalRollbackOnly(); doCommit(status); } else if (isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = status.isGlobalRollbackOnly(); } if (unexpectedRollback) { throw new UnexpectedRollbackException ( "Transaction silently rolled back because it has been marked as rollback-only" ); } } catch (UnexpectedRollbackException ex) { triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); throw ex; } catch (TransactionException ex) { if (isRollbackOnCommitFailure()) { doRollbackOnCommitException(status, ex); } else { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); } throw ex; } catch (RuntimeException | Error ex) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, ex); throw ex; } try { triggerAfterCommit(status); } finally { triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); } } finally { cleanupAfterCompletion(status); } } }
5. 总结
通过springboot项目初始化时会根据TransactionAutoConfiguration
加载@EnableTransactionManagement
,然后通过TransactionManagementConfigurationSelector
扫描加载ProxyTransactionManagementConfiguration
,进而初始化一个TransactionInterceptor
和TransactionAttributeSource
Bean对象
当有@Transactional
注解的bean初始化时在初始化完成时的popularbean()
中变成代理的bean
TransactionManager
是很重要的一个类,关于jdbc的相关操作都放置在内部,且其是一个静态的类,内部通过ThreadLoca
l维护了当前的访问数据库信息,后续需要用到的地方如mabatis就直接从ThreadLocal
中拿到就可以了
6. 注意事项
初始化的TransactionInterceptor
中的TransactionManager
默认是为空的,也不注入,当连接获取TransactionManager
时再懒加载从BeanFactory
中获取
由于默认是通过动态代理执行的@Transactional
增强,因此方法内部调用是不能开启事务的,若有这方面的需求可以用编程式事务或修改代理方式为aspectj的方式