SpringBoot中关于数据源的相关配置
Java知识点总结:想看的可以从这里进入
目录
- 1.7、数据源的相关配置
1.7、数据源的相关配置
在数据库访问过程中,“数据源”是最重要的概念之一,目前,在市面上有很多优秀的开源数据源,例如 DBCP、C3P0、Druid、HikariCP 等等,SpringBoot默认采用了HikariCP 。
SpringBoot用来配置数据源的类为:DataSourceAutoConfiguration,
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({
DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({
DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
}
它内部有五个内部类:其中有2个为配置类(数据源、数据连接池),3个为限制条件类):
EmbeddedDatabaseConfiguration:嵌入式数据库配置
通过
@Conditional(EmbeddedDatabaseCondition.class)
注解引入内部的限制条件类,检测容器中是否已经存在池化数据源(PooledDataSource),若不存在,通过@Import 注解引入 EmbeddedDataSourceConfiguration 类来向容器中添加一个内嵌的数据源(DataSource),若存在,则 EmbeddedDatabaseConfiguration 不能被实例化@Configuration(proxyBeanMethods = false)
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({
DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
通过@Import导入EmbeddedDataSourceConfiguration,它向容器中添加了一个 Spring Boot 内嵌的数据源
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(DataSourceProperties.class)
public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {
private ClassLoader classLoader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
//向容器中添加 Spring Boot 内嵌的数据源,支持 HSQL,H2 和 DERBY 三种数据库
@Bean(destroyMethod = "shutdown")
public EmbeddedDatabase dataSource(DataSourceProperties properties) {
//配置默认的数据源
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseConnection.get(this.classLoader).getType())
.setName(properties.determineDatabaseName()).build();
}
}
PooledDataSourceConfiguration:池化数据源配置
通过
@Conditional(PooledDataSourceCondition.class)
用来检测容器中是否已经存在池化数据源的,若存在,可以向容器中添加池化数据源。@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({
DataSource.class, XADataSource.class })
@Import({
DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
@Import 注解引入了 Hikari、Tomcat、Dbcp2、OracleUcp 和 Generic 五个数据源配置类,它们都是 DataSourceConfiguration 的内部类,作用是向容器中添加指定的数据源
@Configuration(proxyBeanMethods = false) //当前类是一个配置类;
@ConditionalOnClass(HikariDataSource.class) //容器中没有用户自定义的数据源时,该配置类才会被实例化;
@ConditionalOnMissingBean(DataSource.class) //必须在类路径中存在 HikariDataSource时,才会实例化。
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
static class Hikari {
//在配置文件中配置了 spring.datasource.type = com.zaxxer.hikari.HikariDataSource或者不配置 spring.datasource.type(即默认情况)时,Hikari 才会被实例化。
@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
PooledDataSourceCondition:合并数据源条件,主要用来检测容器中是否已经存在池化数据源(PooledDataSource)。
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 {
}
}
PooledDataSourceAvailableCondition:测试支持的连接池是否可用的Condition 。
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());
}
}
EmbeddedDatabaseCondition:检测何时可以使用嵌入式DataSource类型的Condition ,如果一个池化的DataSource可用,它总是优先于EmbeddedDatabase 。
static class EmbeddedDatabaseCondition extends SpringBootCondition {
//数据源 URL 属性
private static final String DATASOURCE_URL_PROPERTY = "spring.datasource.url";
//合并条件
private final SpringBootCondition pooledCondition = new PooledDataSourceCondition();
//
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("EmbeddedDataSource");
if (hasDataSourceUrlProperty(context)) {
return ConditionOutcome.noMatch(message.because(DATASOURCE_URL_PROPERTY + " is set"));
}
if (anyMatches(context, metadata, this.pooledCondition)) {
return ConditionOutcome.noMatch(message.foundExactly("supported pooled data source"));
}
EmbeddedDatabaseType type = EmbeddedDatabaseConnection.get(context.getClassLoader()).getType();
if (type == null) {
return ConditionOutcome.noMatch(message.didNotFind("embedded database").atAll());
}
return ConditionOutcome.match(message.found("embedded database").items(type));
}
private boolean hasDataSourceUrlProperty(ConditionContext context) {
Environment environment = context.getEnvironment();
if (environment.containsProperty(DATASOURCE_URL_PROPERTY)) {
try {
return StringUtils.hasText(environment.getProperty(DATASOURCE_URL_PROPERTY));
}
catch (IllegalArgumentException ex) {
// Ignore unresolvable placeholder errors
}
}
return false;
}
}
还没有评论,来说两句吧...