Springboot DataSources 自动配置原理

Springboot DataSources 自动配置原理

2022-9-6·devcxl
devcxl

本文通过阅读SpringBoot源码分析了Springboot中DataSources的自动配置原理

DataSources自动配置原理

配置文件 application.yml 配置数据源配置

application.yml
spring:
  datasource:
    url: jdbc:mysql//127.0.0.1:3306/test
    username: root
    password: 123456
    type: com.mysql.cj.jdbc.MysqlDataSource
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.java
@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(
    type = {"io.r2dbc.spi.ConnectionFactory"}
)
// 以上两个注解指明了当DataSource.class, EmbeddedDatabaseType.class两个类存在且io.r2dbc.spi.ConnectionFactory类型的Bean不存在时 @Configuration注解才会生效
@AutoConfigureBefore({SqlInitializationAutoConfiguration.class})
// 指明当前配置类将在`SqlInitializationAutoConfiguration.class`加载之前加载

@EnableConfigurationProperties({DataSourceProperties.class})
// 指明自动注入带有ConfigurationProperties注解的DataSourceProperties类

@Import({DataSourcePoolMetadataProvidersConfiguration.class, InitializationSpecificCredentialsDataSourceInitializationConfiguration.class, SharedCredentialsDataSourceInitializationConfiguration.class})
// 将注解中的类导入到IOC容器中
public class DataSourceAutoConfiguration {

    /** 略... **/

	@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 })
    // 加载 DataSourceConfiguration下的静态类时,根据相应静态类的注解条件进行加载 
	protected static class PooledDataSourceConfiguration {
	}

    static class PooledDataSourceCondition extends AnyNestedCondition {
		PooledDataSourceCondition() {
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		}
		@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
		static class ExplicitType {
		}
		@Conditional(PooledDataSourceAvailableCondition.class)
		static class PooledDataSourceAvailable {
		}
	}

    static class PooledDataSourceAvailableCondition extends SpringBootCondition {
		@Override
		public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
			ConditionMessage.Builder message = ConditionMessage.forCondition("PooledDataSource");
			if (DataSourceBuilder.findType(context.getClassLoader()) != null) {
				return ConditionOutcome.match(message.foundExactly("supported DataSource"));
			}
			return ConditionOutcome.noMatch(message.didNotFind("supported DataSource").atAll());
		}
	}

     /** 略... **/
}

DataSourceConfiguration下的通用数据源为例,源码如下:

org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.java
abstract class DataSourceConfiguration {
    
    /** 略... **/

    @Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type")
    // 当DataSource类型的Bean不存在且配置文件存在"spring.datasource.type"配置时 创建通用类型数据源
	static class Generic {
		@Bean
		DataSource dataSource(DataSourceProperties properties) {
			return properties.initializeDataSourceBuilder().build();
		}
	}
}
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.java
@ConfigurationProperties(prefix = "spring.datasource")
// 加载"spring.datasource"前缀的配置
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {

    /** 略... **/

    // 从此方法可以得知 数据源是由 DataSourceBuilder 类来构建的
	public DataSourceBuilder<?> initializeDataSourceBuilder() {
		return DataSourceBuilder.create(getClassLoader()).type(getType()).driverClassName(determineDriverClassName())
				.url(determineUrl()).username(determineUsername()).password(determinePassword());
	}

    /** 略... **/

}

org.springframework.boot.jdbc.DataSourceBuilder 类中包含了数据源创建的具体实现 有兴趣的请自行探究

总结: Springboot DataSources 的自动配置流程大致为

Springboot在启动后 扫描到带有 @Configuration注解的 DataSourceAutoConfiguration

满足一定条件的DataSourceAutoConfiguration类将DataSourceProperties带入IOC容器并加载application.yml文件中的配置

DataSourceAutoConfiguration.PooledDataSourceConfiguration在加载时将DataSourceConfiguration下的静态类引入IOC容器

DataSourceConfiguration下的静态类根据条件进行加载,各种数据源的创建方式由spring.datasource.type填写的类决定

Generic(通用方式)外,Springboot内置的数据源仅支持 Tomcat,Hikari,Dbcp2,OracleUcp 四种

如误请指正!