SpringBoot中关于数据源的相关配置

Java知识点总结:想看的可以从这里进入

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个为限制条件类):

  1. 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();
        }
    
    }
    
  2. 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;
        }
    }
    
  3. 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 {
          
          
        }
    }
    
  4. 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());
        }
    
    }
    
  5. 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;
        }
    
    }
    

猜你喜欢

转载自blog.csdn.net/yuandfeng/article/details/129709309