SpringDataSourceAndTransaction-自动配置

总结摘要
Spring 数据源与事务源码自动配置

数据源与事务相关的自动配置类

基于 Web Servlet 与 JDBC 数据源场景

自动配置类

自动配置属性文件

配置文件 org.springframework.boot.autoconfigure.AutoConfiguration.importsspring-autoconfigure-metadata.properties

  1. 文件路径 spring-boot-autoconfigure-2.7.18.jar!/META-INF/spring-autoconfigure-metadata.properties
  2. 文件路径spring-boot-autoconfigure-2.7.18-sources.jar!/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

JDBC 数据源与事务相关自动配置类

  1. 全量相关类
    1. org.springframework.boot.autoconfigure.jdbc.*
    2. org.springframework.boot.autoconfigure.transaction.*
  2. 重点类
    1. org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
    2. org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
    3. org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

数据源自动配置类

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

  • 注解 import 引入DataSourcePoolMetadataProvidersConfiguration
  • 声明@EnableConfigurationProperties(DataSourceProperties.class),以获取配置信息。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
@AutoConfiguration(before = SqlInitializationAutoConfiguration.class)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import(DataSourcePoolMetadataProvidersConfiguration.class)
public class DataSourceAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@Conditional(EmbeddedDatabaseCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import(EmbeddedDataSourceConfiguration.class)
	protected static class EmbeddedDatabaseConfiguration {

	}

	@Configuration(proxyBeanMethods = false)
	@Conditional(PooledDataSourceCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
			DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
	protected static class PooledDataSourceConfiguration {

	}
}
1
2
3
4
5
6
7
// 数据源 HikariDataSource
--> org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari#dataSource
    --> 创建数据源
        --|> org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration#createDataSource
        --> 支持读取用户自定义配置的 spring 标准配置信息
            --> org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
            --> `@ConfigurationProperties(prefix = "spring.datasource")`

事务自动配置类

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
@AutoConfiguration
@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)
	public TransactionalOperator transactionalOperator(ReactiveTransactionManager transactionManager) {
		return TransactionalOperator.create(transactionManager);
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
	public static class TransactionTemplateConfiguration {

		@Bean
		@ConditionalOnMissingBean(TransactionOperations.class)
		public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
			return new TransactionTemplate(transactionManager);
		}

	}

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

		}

	}

    // 略。
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnBean(AbstractTransactionAspect.class)
	static class AspectJTransactionManagementConfiguration {

		@Bean
		static LazyInitializationExcludeFilter eagerTransactionAspect() {
			return LazyInitializationExcludeFilter.forBeanTypes(AbstractTransactionAspect.class);
		}

	}

}
1
2
3
4
5
6
7
8
9
// 事务自动配置类
// org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
--> EnableTransactionManagementConfiguration
    --|> 启用注解`@EnableTransactionManagement`。
    --|> 该类中存在2个 bean互斥),均声明了该注解2个 bean 分别是`JdkDynamicAutoProxyConfiguration``CglibAutoProxyConfiguration`。
--> TransactionManagerCustomizers
    --> 收集`PlatformTransactionManagerCustomizer`并封装
--> TransactionTemplate
    --> new TransactionTemplate(transactionManager);

注解@EnableTransactionManagementimport 引入TransactionManagementConfigurationSelector,注册了2个 bean,分别为AutoProxyRegistrarProxyTransactionManagementConfiguration

ProxyTransactionManagementConfiguration继承自AbstractTransactionManagementConfiguration

注解源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// org.springframework.transaction.annotation.EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    // Indicate whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false). The default is false. Applicable only if mode() is set to AdviceMode.PROXY.
    // 指示是否创建基于子类的(CGLIB)代理(true),而不是标准的基于 Java 接口的代理(false)。默认值为 false。仅当 mode() 设置为 AdviceMode.PROXY 时适用。
	boolean proxyTargetClass() default false;

    // Indicate how transactional advice should be applied. The default is AdviceMode.PROXY.
    // 指示事务性通知应该如何应用。默认值是 AdviceMode.PROXY。
    // 注意,Spring 中的标准 JDK 动态代理与基于 CGLIB 的动态代理,均对应`AdviceMode.PROXY`。
	AdviceMode mode() default AdviceMode.PROXY;

    // Indicate the ordering of the execution of the transaction advisor when multiple advices are applied at a specific joinpoint. The default is Ordered.LOWEST_PRECEDENCE.
    // 指示当多个通知应用于特定连接点时,事务通知器的执行顺序。默认值是 Ordered.LOWEST_PRECEDENCE。
	int order() default Ordered.LOWEST_PRECEDENCE;
}

AutoProxyRegistrar

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// org.springframework.context.annotation.AutoProxyRegistrar

作用是注册`InfrastructureAdvisorAutoProxyCreator`。
--> org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.beans.factory.support.BeanNameGenerator)
    --> org.springframework.context.annotation.AutoProxyRegistrar#registerBeanDefinitions
        --> org.springframework.aop.config.AopConfigUtils#registerAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry)
            --> org.springframework.aop.config.AopConfigUtils#registerAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
                --> 注册`InfrastructureAdvisorAutoProxyCreator`。registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);

触发时机
--> org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
    --> org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
        --> org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
            --> for-each registrars调用接口方法`registerBeanDefinitions`。
                --|> 接口方法完整签名`org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.beans.factory.support.BeanNameGenerator)`。

AutoProxyRegistrar#registerBeanDefinitions方法注册 AOP 类时,底层调用了 org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired

该方法仅允许注册下列三个AutoProxyCreator其中之一,优先级按顺序递增,优先级高的类会覆盖优先级低的,即 AnnotationAwareAspectJAutoProxyCreator的优先级是最高的。举例,如果先注册InfrastructureAdvisorAutoProxyCreator,再注册AnnotationAwareAspectJAutoProxyCreator,则最终有且仅有AnnotationAwareAspectJAutoProxyCreator注册成功。

这也是 proxyTargetClass 属性同时影响 @Transactional@Async的原因,因为它们底层会使用同一个类实例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// org.springframework.aop.config.AopConfigUtils
public abstract class AopConfigUtils {
	static {
		// Set up the escalation list...
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
	}

	@Nullable
	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)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}

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

ProxyTransactionManagementConfiguration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

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

    // 默认此时 txManager 为空。在后续逻辑中注入。
    // 如果用户自定义1个`TransactionManagementConfigurer`提供`TransactionManager`,则此时不为空,并自动注入。
	@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;
	}

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration
`ProxyTransactionManagementConfiguration`继承自`AbstractTransactionManagementConfiguration`。

// `AbstractTransactionManagementConfiguration`中自动配置
--> TransactionalEventListenerFactory
    --|> 创建`TransactionalApplicationListener`的实现类`TransactionalApplicationListenerMethodAdapter`。
    --|> new TransactionalApplicationListenerMethodAdapter(beanName, type, method);

// `ProxyTransactionManagementConfiguration`中自动配置
--> `TransactionAttributeSource`的实现类`AnnotationTransactionAttributeSource`。
    --|> new AnnotationTransactionAttributeSource();
    --> 默认创建`SpringTransactionAnnotationParser`,作用是解析声明事务属性的注解`@Transactional`。
        --|> `new SpringTransactionAnnotationParser()`。
        --|> SpringTransactionAnnotationParser `TransactionAnnotationParser`的实现类之一
    --> 如果 classpath 中存在 jta  ejb 相关的依赖则创建对应的`TransactionAnnotationParser`的实现类
--> TransactionInterceptor
    --|> 注册拦截器
    --|> 将被注册到`Advisor`中构建为切面
    --> 默认此时 txManager 为空在后续逻辑中注入
        --|> 如果用户自定义1个`TransactionManagementConfigurer`提供`TransactionManager`,则此时不为空并自动注入
--> BeanFactoryTransactionAttributeSourceAdvisor
    --|> new BeanFactoryTransactionAttributeSourceAdvisor();

工具 JdbcTemplate 自动配置类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// org.springframework.boot.autoconfigure.jdbc.JdbcTemplateConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {

	@Bean
	@Primary
	JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
		JdbcProperties.Template template = properties.getTemplate();
		jdbcTemplate.setFetchSize(template.getFetchSize());
		jdbcTemplate.setMaxRows(template.getMaxRows());
		if (template.getQueryTimeout() != null) {
			jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
		}
		return jdbcTemplate;
	}
}
1
2
3
4
5
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateConfiguration
--> 创建`JdbcTemplate`并进行配置`new JdbcTemplate(dataSource);`。
    --|> org.springframework.boot.autoconfigure.jdbc.JdbcTemplateConfiguration#jdbcTemplate
    --> org.springframework.boot.autoconfigure.jdbc.JdbcProperties
    --> `@ConfigurationProperties(prefix = "spring.jdbc")`

END