Spring之声明式事务

入口

Spring中,我们可以通过@EnableTransactionManagement开启声明式事务;但在SpringBoot我们发现不打这个注解也开启了声明式事务,这是为什么呢?答案就在org.springframework.boot:spring-boot-autoconfigure这个包里的spring.factories(spring.factories放了很多需要容器管理的实例的类路径;三方jar包可以通过这种方式将自己的一些Bean交托给Spring容器管理), 这个文件告诉Spring容器,它有个org.springframework.boot.autoconfigure.transaction.TransactionAutoConfigurationJavaConfig要托付。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
		DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {
    ...

	@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 {

		}

	}

}

spring.aop.proxy-target-class默认为true

注解@EnableTransactionManagement

@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;
}

又看到了熟悉的@Import注解,这个注解在@Enablexxxx系列的注解中经常看到。导入的是ImportSelector的实现类,会执行类里的String[] selectImports(AnnotationMetadata importingClassMetadata);方法

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    // 这个方法在父类`AdviceModeImportSelector`的`selectImports(org.springframework.core.type.AnnotationMetadata)`中被调用
	@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() {
		...
	}
}

// org.springframework.context.annotation.AdviceModeImportSelector#selectImports
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
	Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
	Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
    // 获取@EnableTransactionManagement的全部属性
	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()));
	}
    // 获取@EnableTransactionManagement里的`mode`属性值,这里是`PROXY`
	AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
	// 调用`TransactionManagementConfigurationSelector`的`selectImports(AdviceMode adviceMode)`
	// 这里返回的是new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}
	String[] imports = selectImports(adviceMode);
	if (imports == null) {
		throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
	}
	return imports;
}

最终添加的Bean方法如下:

public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    // 这是一个`PointcutAdvisor`,增强器
	@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();
	}

    // 这是一个`MethodInterceptor`,主要处理事务的逻辑
	@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;
	}

}
// 父类`AbstractTransactionManagementConfiguration`
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {

	@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
		return new TransactionalEventListenerFactory();
	}

}

进行到这里,通过@EnableTransactionManagement,我们添加了一个ImportBeanDefinitionRegistrar->AutoProxyRegistrar,以及4个@Bean方法。AutoProxyRegistrar里我们注入了org.springframework.aop.config.internalAutoProxyCreator这个bean,是InfrastructureAdvisorAutoProxyCreator类。在SpringBoot里,我们有自动加载AopAutoConfiguration,会用AnnotationAwareAspectJAutoProxyCreator替换InfrastructureAdvisorAutoProxyCreator。4个Bean分别为:

  • BeanFactoryTransactionAttributeSourceAdvisor: 这是最终的一个Advisor;
  • TransactionAttributeSource: 从配置、源级别的元数据属性或其他任何地方获取事务属性;这里用的是AnnotationTransactionAttributeSource,通过SpringTransactionAnnotationParser解析
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值