SpringBoot系列:事物加载过程(一)
SpringBoot系列:事物创建过程(二)
SpringBoot系列:事物提交回滚过程(三)
我们都知道事物执行过程是AOP
,所以加载过程也一定有AOP
的加载过程,在SpringBoot中,是通过自动装配作为入口点,然后转换为加载AOP的执行流程。
SpringBoot启动会扫描spring.factories
文件,加载所有需要自动装配的类信息,但我看是springboot-autoconfigura-2.75版本多了一个org.springframework.boot.autoconfigure.AutoConfiguration.imports
,TransactionAutoConfiguration 就在其中,该类就是事物自动装配的入口。
@AutoConfiguration(after = { JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
1、需要先存在PlatformTransactionManager的bean,这儿使用的jdbc,也可指定其他的。
@ConditionalOnClass(PlatformTransactionManager.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)
2、响应式事物的管理器
public TransactionalOperator transactionalOperator(ReactiveTransactionManager transactionManager) {
return TransactionalOperator.create(transactionManager);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
3、声明式事物的模板,这儿把事物管理器也就是jdbc注入进去了。
public static class TransactionTemplateConfiguration {
@Bean
@ConditionalOnMissingBean(TransactionOperations.class)
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
return new TransactionTemplate(transactionManager);
}
}
4、重点在这儿,开启事物
@Configuration(proxyBeanMethods = false)
4.1、必须存在事物管理器才会加载。
@ConditionalOnBean(TransactionManager.class)
4.2、不存在AbstractTransactionManagementConfiguration,代表事物管理的配置类已经加载过了,无需再次加载
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
5、这儿两种模式,JDK动态代理或CGLIB动态代理,根据proxy-target-class来确定模式,
在springboot2.0+默认从jdk改为了cglib,也就是默认都为true。
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "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 {
}
}
}
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
···省略
}
@EnableTransactionManagement
注解自动配置类加载的重点,通过@Import
进一步的加载。
TransactionManagementConfigurationSelector
类是一个 ImportSelector,在解析@Import
的过程中会进入 selectImports ()
方法。
@Override
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
1、这儿的class类就是EnableTransactionManagement
Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
2、EnableTransactionManagement内部的属性
proxyTargetClass、mode、order
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()));
}
3、获取mode属性,默认是PROXY
AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
4、根据mode获取要加载的类
这儿获取到的是AutoProxyRegistrar.class和ProxyTransactionManagementConfiguration.class
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;
}
}
观察AutoProxyRegistrar以及ProxyTransactionManagementConfiguration具体做了什么。
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
1、是CglibAutoProxyConfiguration,获取他的注解列表也就是
@Configuration、@EnableTransactionManagement、@ConditionalOnProperty
不过这儿只对EnableTransactionManagement进行处理
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
2、因为Configuration以及ConditionalOnProperty不满足下面的if判断,所以不处理
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
3、PROXY模式
if (mode == AdviceMode.PROXY) {
3.1、注册InfrastructureAdvisorAutoProxyCreator,但是并一定会注册成功,
AOP有多个代理创建的类,会选择优先级最高的
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
3.2、将proxyTargetClass为true属性设置上去
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
3.1处AOP有三种代理创建的类,分别是
InfrastructureAdvisorAutoProxyCreator:
事物所用的,也就是本章讲解的。
AspectJAwareAdvisorAutoProxyCreator:
AnnotationAwareAspectJAutoProxyCreator:
扫描切面,是上一个的子类
因为上述三个类都实现了BeanPostProcessor
接口,所以在Spring初始化的前后会进行前置处理以及后置处理,这儿同样也是AOP的入口,所以事物就是通过AOP来实现的。
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
1、内部封装了下面两个bean,后续只需要获取该advisor就可以了
@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)
2、用来获取事物属性的类
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
3、事物拦截器,执行具体方法的时候会执行事物的拦截器。后面讲。
@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;
}
}
这儿往Spring容器中添加了两个类,一个用来获取事物的属性,一个用来用作后续真正执行事物的拦截器。
在往后面走就是与AOP的流程一致,这儿不多做讲解,可以看我另一篇文章:
Spring之AOP系列源码分析
这儿只着重解析一些事物单独执行的部分:
进入后置处理之后,在Spring之AOP系列源码分析代码块十五中的,进入matches方法,这儿是事物内部单独进行判断当前加载的类是否符合增强条件。
@Override
public boolean matches(Method method, Class<?> targetClass) {
1、这儿就是上面 2.5 内的获取属性的类,通过否存在事物属性判断当前加载的类是否需要创建代理
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
1、首先通过自动装配,进行加载TransactionAutoConfiguration
类,进一步的加载声明式事物、编程式事物以及创建CGLIB还是JDK动态代理。
2、TransactionManagementConfigurationSelector
是 Selector
接口的子类,通过注解的mode = PROXY
注册了两个类
AutoProxyRegistrar
和ProxyTransactionManagementConfiguration
。
3、AutoProxyRegistrar
注册了 自动代理的创建者,也就是有三种的某一个,一般是AnnotationAwareAspectJAutoProxyCreator
,该类实现了BeanPostProcessor
,在bean初始化前后调用。
ProxyTransactionManagementConfiguration
:注册事物相关信息,如事物属性,事物的拦截器,以及是否需要创建代理都是由该类完成。