相关阅读

  • Spring Boot源码简析 事务管理
  • Spring Boot源码简析 @EnableAspectJAutoProxy
  • Spring Boot源码简析 @EnableAsync
  • Spring Boot源码简析 @EnableCaching

TransactionAutoConfiguration

Spring框架提供@Transactional注解来支持注解驱动的事务管理;
Spring Boot框架默认开启注解驱动的事务管理,即通过TransactionAutoConfiguration实现事务管理自动配置,代码如下:

@Configuration
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class,Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic TransactionManagerCustomizers platformTransactionManagerCustomizers(ObjectProvider<List<PlatformTransactionManagerCustomizer<?>>> customizers) {return new TransactionManagerCustomizers(customizers.getIfAvailable());}@Configuration@ConditionalOnSingleCandidate(PlatformTransactionManager.class)public static class TransactionTemplateConfiguration {private final PlatformTransactionManager transactionManager;public TransactionTemplateConfiguration(PlatformTransactionManager transactionManager) {this.transactionManager = transactionManager;}@Bean@ConditionalOnMissingBeanpublic TransactionTemplate transactionTemplate() {return new TransactionTemplate(this.transactionManager);}}@Configuration@ConditionalOnBean(PlatformTransactionManager.class)@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)public static class EnableTransactionManagementConfiguration {@Configuration@EnableTransactionManagement(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)public static class JdkDynamicAutoProxyConfiguration {}@Configuration@EnableTransactionManagement(proxyTargetClass = true)// 当spring.aop.proxy-target-class属性值为true或者不存在时生效@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)public static class CglibAutoProxyConfiguration {}}
}

根据TransactionAutoConfiguration的配置信息可知,当引入PlatformTransactionManager(spring-tx提供)时,该配置类自动生效;
DataSourceTransactionManagerAutoConfiguration会创建TransactionManager,如果当前已存在AbstractTransactionManagementConfiguration,即ProxyTransactionManagementConfiguration,那么意味着已经引入@EnableTransactionManagement注解(ProxyTransactionManagementConfiguration只会被@EnableTransactionManagement注解引入),因此EnableTransactionManagementConfiguration不需要生效;否则就会生效,从而引入@EnableTransactionManagement注解;
EnableTransactionManagementConfiguration生效的情况下,除非指定spring.aop.proxy-target-class配置项为false,此时JdkDynamicAutoProxyConfiguration会生效,否则CglibAutoProxyConfiguration生效,这两配置都会引入@EnableTransactionManagement注解,只是注解的proxyTargetClass属性值不同,该注解会开启事务管理,其实就是引入ProxyTransactionManagementConfiguration

@EnableTransactionManagement

源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {// 代理模式:CGLIB or JDK Interface// 默认为false,表示基于JDK Interface// 设置为true,会影响所有需要代理的Spring管理的Beanboolean proxyTargetClass() default false;// 代理应用模式:Proxy or AspectJ// Proxy模式只允许通过代理拦截调用,不会拦截同一类中的本地调用// AspectJ模式下,proxyTargetClass()无效,会拦截同一类中的本地调用AdviceMode mode() default AdviceMode.PROXY;// 特定连接点应用多个建议时,事务操作的执行顺序int order() default Ordered.LOWEST_PRECEDENCE;}

简析

通过Import机制,引入TransactionManagementConfigurationSelector

@Import(TransactionManagementConfigurationSelector.class)

TransactionManagementConfigurationSelector继承自AdviceModeImportSelectorAdviceModeImportSelector实现支持AdviceMode算法模板,且支持通用的@EnableXxx注解模式,代码如下:

public final String[] selectImports(AnnotationMetadata importingClassMetadata) {// 获取本类支持的注解类型// 对于TransactionManagementConfigurationSelector来说为EnableTransactionManagementClass<?> 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 adviceMode = attributes.getEnum(this.getAdviceModeAttributeName());// 根据AdviceMode获取引入配置类信息// 该方法由子类实现算法细节String[] imports = selectImports(adviceMode);if (imports == null) {throw new IllegalArgumentException(String.format("Unknown AdviceMode: '%s'", adviceMode));}return imports;
}@Nullable
protected abstract String[] selectImports(AdviceMode adviceMode);

TransactionManagementConfigurationSelector实现了算法细节selectImports,代码如下:

protected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};default:return null;}
}

根据@EnableTransactionManagement(proxyTargetClass = true)配置会引入AutoProxyRegistrarProxyTransactionManagementConfiguration

AutoProxyRegistrar

AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,用于向容器里注册自动代理创建器AutoProxyCreator,代码如下:

/*** importingClassMetadata : 通过Import引入该类的配置类的元数据信息,本例中配置类为CglibAutoProxyConfiguration* registry : Bean定义容器*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean candidateFound = false;// 获取配置类的注解列表// 本例中注解有://  @Configuration//  @EnableTransactionManagement//  @ConditionalOnPropertySet<String> annoTypes = importingClassMetadata.getAnnotationTypes();// 遍历注解列表for (String annoType : annoTypes) {// 获取注解的属性数据AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);if (candidate == null) {continue;}// 获取mode属性值Object mode = candidate.get("mode");// 获取proxyTargetClass属性值Object proxyTargetClass = candidate.get("proxyTargetClass");// 过滤出@EnableTransactionManagement注解if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&Boolean.class == proxyTargetClass.getClass()) {candidateFound = true;// 本例中,mode为AdviceMode.PROXY,proxyTargetClass为trueif (mode == AdviceMode.PROXY) {AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);if ((Boolean) proxyTargetClass) {// 使用subclass-based proxyAopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);return;}}}}if (!candidateFound && logger.isWarnEnabled()) {// 异常LOG记录String name = getClass().getSimpleName();logger.warn(String.format("%s was imported but no annotations were found " +"having both 'mode' and 'proxyTargetClass' attributes of type " +"AdviceMode and boolean respectively. This means that auto proxy " +"creator registration and configuration may not have occurred as " +"intended, and components may not be proxied as expected. Check to " +"ensure that %s has been @Import'ed on the same class where these " +"annotations are declared; otherwise remove the import of %s " +"altogether.", name, name, name));}
}

核心逻辑为AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);,代码如下:

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {return registerAutoProxyCreatorIfNecessary(registry, null);
}public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,@Nullable Object source) {return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,@Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");// 判断当前容器中是否存在自动代理创建器的Bean定义if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {// 获取已存在的Bean定义BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);// 判断已存在的Bean定义的className和当前是否一致if (!cls.getName().equals(apcDefinition.getBeanClassName())) {// 不一致则使用优先级更高的int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}// 根据当前class创建Bean定义并放入容器中RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;
}public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);// 添加Bean定义的proxyTargetClass属性definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);}
}

ProxyTransactionManagementConfiguration

ProxyTransactionManagementConfiguration是一个配置类,继承自AbstractTransactionManagementConfiguration
AbstractTransactionManagementConfiguration实现了ImportAware接口,会注入@EnableTransactionManagement注解属性数据,同时注入TransactionManagementConfigurer配置,代码如下:

public void setImportMetadata(AnnotationMetadata importMetadata) {// 获取@EnableTransactionManagement注解属性数据this.enableTx = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));if (this.enableTx == null) {throw new IllegalArgumentException("@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());}
}@Autowired(required = false)
void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {if (CollectionUtils.isEmpty(configurers)) {return;}// // TransactionManagementConfigurer bean只能存在一个if (configurers.size() > 1) {throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");}TransactionManagementConfigurer configurer = configurers.iterator().next();// 使用自定义的事务管理器this.txManager = configurer.annotationDrivenTransactionManager();
}@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionalEventListenerFactory transactionalEventListenerFactory() {// 注入监听器工厂,支持@TransactionalEventListener注解标注的方法,来监听事务相关的事件return new TransactionalEventListenerFactory();
}

ProxyTransactionManagementConfiguration会向容器中注入BeanFactoryTransactionAttributeSourceAdvisorTransactionAttributeSourceTransactionInterceptor,代码如下:

@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {// 事务管理核心AdvisorBeanFactoryTransactionAttributeSourceAdvisor 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() {// 事务拦截器TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());if (this.txManager != null) {// 设置事务管理器interceptor.setTransactionManager(this.txManager);}return interceptor;
}

AnnotationTransactionAttributeSource

AnnotationTransactionAttributeSource是基于注解的事务属性源,内部维护TransactionAnnotationParser集合,用于解析类或方法的事务属性,代码如下:

public AnnotationTransactionAttributeSource() {// 默认只能解析public方法this(true);
}public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {this.publicMethodsOnly = publicMethodsOnly;this.annotationParsers = new LinkedHashSet<>(2);// 默认持有SpringTransactionAnnotationParser支持Spring事务注解this.annotationParsers.add(new SpringTransactionAnnotationParser());if (jta12Present) {// 持有JtaTransactionAnnotationParser支持JTS事务注解this.annotationParsers.add(new JtaTransactionAnnotationParser());}if (ejb3Present) {// 持有Ejb3TransactionAnnotationParser支持EJB3事务注解this.annotationParsers.add(new Ejb3TransactionAnnotationParser());}
}protected TransactionAttribute findTransactionAttribute(Method method) {return determineTransactionAttribute(method);
}protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {return determineTransactionAttribute(clazz);
}protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {// 遍历内部的事务注解解析器for (TransactionAnnotationParser annotationParser : this.annotationParsers) {// 解析事务属性TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);if (attr != null) {// 解析成功直接返回return attr;}}return null;
}

SpringTransactionAnnotationParser

SpringTransactionAnnotationParser实现了TransactionAnnotationParser接口,负责解析@Transactional注解,核心代码如下:

public boolean isCandidateClass(Class<?> targetClass) {// 指定类是否可能标注@Transactional注解return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {// 寻找该元素(方法或者类)上是否标注@Transactional注解AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);if (attributes != null) {// 存在,则继续解析@Transactional注解属性return parseTransactionAnnotation(attributes);}else {return null;}
}public TransactionAttribute parseTransactionAnnotation(Transactional ann) {return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
}/*** 进一步解析@Transactional注解属性*/
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");rbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");rbta.setIsolationLevel(isolation.value());rbta.setTimeout(attributes.getNumber("timeout").intValue());String timeoutString = attributes.getString("timeoutString");Assert.isTrue(!StringUtils.hasText(timeoutString) || rbta.getTimeout() < 0,"Specify 'timeout' or 'timeoutString', not both");rbta.setTimeoutString(timeoutString);rbta.setReadOnly(attributes.getBoolean("readOnly"));rbta.setQualifier(attributes.getString("value"));rbta.setLabels(Arrays.asList(attributes.getStringArray("label")));List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {rollbackRules.add(new RollbackRuleAttribute(rbRule));}for (String rbRule : attributes.getStringArray("rollbackForClassName")) {rollbackRules.add(new RollbackRuleAttribute(rbRule));}for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {rollbackRules.add(new NoRollbackRuleAttribute(rbRule));}for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {rollbackRules.add(new NoRollbackRuleAttribute(rbRule));}rbta.setRollbackRules(rollbackRules);return rbta;
}

TransactionInterceptor

TransactionInterceptor继承自TransactionAspectSupport,并实现了MethodInterceptor,代码如下:

public Object invoke(MethodInvocation invocation) throws Throwable {Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {@Override@Nullablepublic Object proceedWithInvocation() throws Throwable {return invocation.proceed();}@Overridepublic Object getTarget() {return invocation.getThis();}@Overridepublic Object[] getArguments() {return invocation.getArguments();}});
}

事务管理的核心处理逻辑在父类TransactionAspectSupport,代码如下:

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) {boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);boolean hasSuspendingFlowReturnType = isSuspendingFunction &&COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {throw new IllegalStateException("Coroutines invocation not supported: " + method);}CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {Class<?> reactiveType =(isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);if (adapter == null) {throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +method.getReturnType());}return new ReactiveTransactionSupport(adapter);});InvocationCallback callback = invocation;if (corInv != null) {callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments());}Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm);if (corInv != null) {Publisher<?> pr = (Publisher<?>) result;return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) :KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation()));}return result;}PlatformTransactionManager ptm = asPlatformTransactionManager(tm);// 获取方法ID字符串final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {// 标准的事务管理:getTransaction/commit/rollback calls.// 创建事务信息,根据事务属性决定是否创建事务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 {Object result;final ThrowableHolder throwableHolder = new ThrowableHolder();try {// 交给事务管理器执行result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {// 准备事务TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);try {// 执行原始方法Object retVal = invocation.proceedWithInvocation();if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);}return retVal;}catch (Throwable ex) {// 判断基于当前异常是否回滚if (txAttr.rollbackOn(ex)) {// RuntimeException可以触发事务回滚(DefaultTransactionAttribute实现)// Spring框架认为Checked的异常属于业务的,coder需要处理if (ex instanceof RuntimeException) {throw (RuntimeException) ex;}else {throw new ThrowableHolderException(ex);}}else {// 无需回滚,但因为发生异常,需要返回nullthrowableHolder.throwable = ex;return null;}}finally {// 清除事务信息cleanupTransactionInfo(txInfo);}});}catch (ThrowableHolderException ex) {throw ex.getCause();}catch (TransactionSystemException ex2) {if (throwableHolder.throwable != null) {logger.error("Application exception overridden by commit exception", throwableHolder.throwable);ex2.initApplicationException(throwableHolder.throwable);}throw ex2;}catch (Throwable ex2) {if (throwableHolder.throwable != null) {logger.error("Application exception overridden by commit exception", throwableHolder.throwable);}throw ex2;}if (throwableHolder.throwable != null) {// 存在异常则需要抛出throw throwableHolder.throwable;}return result;}
}protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {if (txInfo != null && txInfo.getTransactionStatus() != null) {if (logger.isTraceEnabled()) {logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +"] after exception: " + ex);}if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {// 满足事务回滚要求,则回滚事务try {txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {logger.error("Application exception overridden by rollback exception", ex);ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException | Error ex2) {logger.error("Application exception overridden by rollback exception", ex);throw ex2;}}else {// 不满足事务回滚要求,无需回滚事务try {// 提交事务txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {logger.error("Application exception overridden by commit exception", ex);ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException | Error ex2) {logger.error("Application exception overridden by commit exception", ex);throw ex2;}}}
}protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {if (txAttr == null || this.beanFactory == null) {// 直接返回全局事务管理器return getTransactionManager();}// 获取事务属性指定的事务管理器名称String qualifier = txAttr.getQualifier();if (StringUtils.hasText(qualifier)) {// 若指定事务管理器名称,则根据名称查找对应的Beanreturn determineQualifiedTransactionManager(this.beanFactory, qualifier);}else if (StringUtils.hasText(this.transactionManagerBeanName)) {// 指定了全局事务管理器名称,则根据名称查找对应的Beanreturn determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);}else {// 获取全局事务管理器PlatformTransactionManager defaultTransactionManager = getTransactionManager();if (defaultTransactionManager == null) {// 从本地缓存中获取默认事务管理器defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);if (defaultTransactionManager == null) {// 从容器中获取PlatformTransactionManagerdefaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);// 缓存该事务管理器this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);}}return defaultTransactionManager;}
}private PlatformTransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {// 从本地缓存中获取指定名称的事务管理器PlatformTransactionManager txManager = this.transactionManagerCache.get(qualifier);if (txManager == null) {// 本地缓存不存在,则从容器中根据类型和名称查找事务管理器txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, PlatformTransactionManager.class, qualifier);// 缓存该事务管理器,方便下次直接从本地缓存中获取this.transactionManagerCache.putIfAbsent(qualifier, txManager);}return txManager;
}

BeanFactoryTransactionAttributeSourceAdvisor

ProxyTransactionManagementConfiguration中,为BeanFactoryTransactionAttributeSourceAdvisor设置了TransactionInterceptor作为增强,设置了AnnotationTransactionAttributeSource作为事务属性源,代码如下:

private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};

BeanFactoryTransactionAttributeSourceAdvisor内部的PointcutTransactionAttributeSourcePointcut,使用AnnotationTransactionAttributeSource作为事务属性源,实现切入匹配判断,代码如下:

public boolean matches(Method method, @Nullable Class<?> targetClass) {// 不支持TransactionalProxyif (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {return false;}// 获取事务属性源TransactionAttributeSource tas = getTransactionAttributeSource();// 若当前方法存在事务属性则匹配成功return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

TransactionManagementConfigurer

Spring Boot框架默认会提供DataSourceTransactionManagerJpaTransactionManager事务管理器,用户可以通过实现接口TransactionManagementConfigurer来提供自定义PlatformTransactionManager实现;

源码

public interface TransactionManagementConfigurer {PlatformTransactionManager annotationDrivenTransactionManager();
}

配置

@Configuration
public class JdbcConfig implements TransactionManagementConfigurer {@Overridepublic PlatformTransactionManager annotationDrivenTransactionManager() {DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource);return dataSourceTransactionManager;}
}

简析

当自定义TransactionManagementConfigurer实现并放入容器后,AbstractTransactionManagementConfiguration.setConfigurers方法会搜索容器内所有的TransactionManagementConfigurer实现(仅支持一个),并将自定义的事务管理器作为全局默认事务管理器。

@Transactional

源码

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {// 指定事务管理器名称@AliasFor("transactionManager")String value() default "";// 指定事务管理器名称@AliasFor("value")String transactionManager() default "";// 事务传播行为Propagation propagation() default Propagation.REQUIRED;// 事务隔离级别Isolation isolation() default Isolation.DEFAULT;// 事务超时时间int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;// 是否只读boolean readOnly() default false;// 回滚异常类型Class<? extends Throwable>[] rollbackFor() default {};// 回滚异常类名String[] rollbackForClassName() default {};// 不回滚异常类型Class<? extends Throwable>[] noRollbackFor() default {};// 不回滚异常类名String[] noRollbackForClassName() default {};
}

使用

  1. 标注在类上,表示该类的所有方法都被标注;
  2. 标注在方法上,优先于方法所在类上的注解,若存在的话;

和@EnableAsync区别

  • @EnableTransactionManagement借助自动代理创建器AutoProxyCreator实现代理;
  • @EnableAsync借助Bean后置处理器BeanPostProcessor实现代理;

事务不生效原因

  1. 事务切入的方法默认必须是public方法,见AnnotationTransactionAttributeSource
  2. Spring框架只对RuntimeException进行回滚;
  3. 业务和事务在同一个线程中;
  4. 非事务方法调用同类中的事务方法,则事务不生效;
    1. 事务方法调用同类中的事务/非事务方法,调用方法的事务生效;
    2. 非事务方法通过本类的代理对象调用事务方法,被调用方法的事务生效;

Spring Boot源码简析 @EnableTransactionManagement相关推荐

  1. Spring Boot源码简析 @Qualifier

    源码 @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementT ...

  2. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  3. django源码简析——后台程序入口

    django源码简析--后台程序入口 这一年一直在用云笔记,平时记录一些tips或者问题很方便,所以也就不再用博客进行记录,还是想把最近学习到的一些东西和大家作以分享,也能够对自己做一个总结.工作中主 ...

  4. (Ajax)axios源码简析(三)——请求与取消请求

    传送门: axios源码简析(一)--axios入口文件 axios源码简析(二)--Axios类与拦截器 axios源码简析(三)--请求与取消请求 请求过程 在Axios.prototype.re ...

  5. java ArrayList 概述 与源码简析

    ArrayList 概述 与源码简析 1 ArrayList 创建 ArrayList<String> list = new ArrayList<>(); //构造一个初始容量 ...

  6. spring boot 源码解析23-actuate使用及EndPoint解析

    前言 spring boot 中有个很诱人的组件–actuator,可以对spring boot应用做监控,只需在pom文件中加入如下配置即可: <dependency><group ...

  7. 【细读Spring Boot源码】重中之重refresh()

    前言 版本:spring-boot-2.7.3 | spring-context-5.3.22 在Spring Boot启动过程中[细读Spring Boot源码]启动步骤 主流程详情7中applic ...

  8. ffmpeg实战教程(十三)iJKPlayer源码简析

    要使用封装优化ijk就必须先了解ffmpeg,然后看ijk对ffmpeg的C层封装! 这是我看ijk源码时候的笔记,比较散乱.不喜勿喷~ ijk源码简析: 1.ijkplayer_jni.c 封装的播 ...

  9. 【Android项目】本地FM收音机开发及源码简析

    [Android项目]本地FM收音机开发及源码简析 目录 1.概述 2.收音机的基本原理 3.收音机其他信息 RDS功能 4.Android开发FM收音机源码解析 5.App层如何设计本地FM应用 6 ...

最新文章

  1. Linux环境HBase安装配置及使用
  2. 26期Linux20180531 单用户 救援模式 克隆虚拟机 linux机器相互登录
  3. win服务器发展方向是什么?
  4. GPLinker:基于GlobalPointer的事件联合抽取
  5. python语句解释_深入理解python with 语句
  6. java怎么将前端的数据存到关联的表中_Java程序员最可能被考到的14个面试题
  7. 洛谷【P2758】-编辑距离
  8. nginx正确服务react-router应用
  9. 6个座位办公室最佳位置_四人办公室座次的首选最佳座位在哪儿
  10. 想成为企业争抢的目标吗?你需要掌握的五大热门IT技能
  11. 【面向对象】面向对象程序设计测试题4-Java中的类和对象测试
  12. 代码简洁(注意事项)
  13. !!超级筹码理论总结
  14. VMware下CentOS6.8配置GFS文件系统
  15. CC创作共用版权协议,要求署名+非商业+相同方式共享
  16. 常用31个Java机器学习、深度学习、自然语言处理学习库工具
  17. Eclipse Spring Tool Suite常用配置
  18. Linux红外驱动重点解析
  19. python模拟鼠标拖动_python模拟鼠标拖动教程
  20. python文件管理api_python调用有道智云API实现文件批量翻译

热门文章

  1. vlan的几种划分方式
  2. “一品四境”学JAVA——书籍推荐/路径规划
  3. 计算机的玩法教程,第五人格电脑版怎么玩 电脑版玩法教程
  4. 但得有心能自奋,何愁他日不雄飞
  5. RepVGG: Making VGG-style ConvNets Great Again
  6. 苹果MacBook电脑应用优化利器CleanMyMac X
  7. 赞!华为19级大牛分享503NoSQL进阶笔记,横扫一切
  8. 睡前做什么有助于睡眠,不妨试试这几个帮助睡眠小妙招
  9. PL-VIO学习+注释
  10. 到底多大并发才算高并发?一文带你全面认识高并发!