数据源与事务相关的自动配置类
基于 Web Servlet 与 JDBC 数据源场景
自动配置类
自动配置属性文件
配置文件 org.springframework.boot.autoconfigure.AutoConfiguration.imports与spring-autoconfigure-metadata.properties。
- 文件路径
spring-boot-autoconfigure-2.7.18.jar!/META-INF/spring-autoconfigure-metadata.properties。 - 文件路径
spring-boot-autoconfigure-2.7.18-sources.jar!/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。
JDBC 数据源与事务相关自动配置类
- 全量相关类
org.springframework.boot.autoconfigure.jdbc.*org.springframework.boot.autoconfigure.transaction.*
- 重点类
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfigurationorg.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfigurationorg.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,分别为AutoProxyRegistrar和ProxyTransactionManagementConfiguration。
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