SpringBoot事物的加载过程

文章目录

  • SpringBoot事物的加载过程
  • 同系列
  • 一、前言
  • 二、事物自动装配加载
  • 2.1、TransactionAutoConfiguration类
  • 2.2、AdviceModeImportSelector & selectImports方法
  • 2.3、TransactionManagementConfigurationSelector & selectImports
  • 2.4、AutoProxyRegistrar类
  • 2.5、 ProxyTransactionManagementConfiguration 类
  • 2.6、TransactionAttributeSourcePointcut & matches
  • 三、总结



一、前言

我们都知道事物执行过程是AOP,所以加载过程也一定有AOP的加载过程,在SpringBoot中,是通过自动装配作为入口点,然后转换为加载AOP的执行流程。

二、事物自动装配加载

SpringBoot启动会扫描spring.factories文件,加载所有需要自动装配的类信息,但我看是springboot-autoconfigura-2.75版本多了一个org.springframework.boot.autoconfigure.AutoConfiguration.importsTransactionAutoConfiguration 就在其中,该类就是事物自动装配的入口。

2.1、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 ()方法。

2.2、AdviceModeImportSelector & 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;
	}

2.3、TransactionManagementConfigurationSelector & selectImports

@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具体做了什么。

2.4、AutoProxyRegistrar类

@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:事物所用的,也就是本章讲解的。 <tx:annotation-driven />
AspectJAwareAdvisorAutoProxyCreator: <aop:config />
AnnotationAwareAspectJAutoProxyCreator:扫描切面,是上一个的子类 <aop:aspectj-autoproxy />

因为上述三个类都实现了BeanPostProcessor接口,所以在Spring初始化的前后会进行前置处理以及后置处理,这儿同样也是AOP的入口,所以事物就是通过AOP来实现的。

2.5、 ProxyTransactionManagementConfiguration 类

@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容器中添加了两个类,一个用来获取事物的属性,一个用来用作后续真正执行事物的拦截器。


这儿只着重解析一些事物单独执行的部分:

进入后置处理之后,在Spring之AOP系列源码分析代码块十五中的,进入matches方法,这儿是事物内部单独进行判断当前加载的类是否符合增强条件。

2.6、TransactionAttributeSourcePointcut & 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、TransactionManagementConfigurationSelectorSelector接口的子类,通过注解的mode = PROXY 注册了两个类

AutoProxyRegistrarProxyTransactionManagementConfiguration

3、AutoProxyRegistrar注册了 自动代理的创建者,也就是有三种的某一个,一般是AnnotationAwareAspectJAutoProxyCreator,该类实现了BeanPostProcessor,在bean初始化前后调用。

ProxyTransactionManagementConfiguration:注册事物相关信息,如事物属性,事物的拦截器,以及是否需要创建代理都是由该类完成。