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