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

拼搏现实的明天。 2024-03-25 23:17 141阅读 0赞

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

目录

      • 1.7、数据源的相关配置

1.7、数据源的相关配置

在数据库访问过程中,“数据源”是最重要的概念之一,目前,在市面上有很多优秀的开源数据源,例如 DBCP、C3P0、Druid、HikariCP 等等,SpringBoot默认采用了HikariCP 。

SpringBoot用来配置数据源的类为:DataSourceAutoConfiguration,

  1. @Configuration(proxyBeanMethods = false)
  2. @ConditionalOnClass({
  3. DataSource.class, EmbeddedDatabaseType.class })
  4. @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
  5. @EnableConfigurationProperties(DataSourceProperties.class)
  6. @Import({
  7. DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
  8. public class DataSourceAutoConfiguration {
  9. }

它内部有五个内部类:其中有2个为配置类(数据源、数据连接池),3个为限制条件类):

  1. EmbeddedDatabaseConfiguration:嵌入式数据库配置

    通过@Conditional(EmbeddedDatabaseCondition.class)注解引入内部的限制条件类,检测容器中是否已经存在池化数据源(PooledDataSource),若不存在,通过@Import 注解引入 EmbeddedDataSourceConfiguration 类来向容器中添加一个内嵌的数据源(DataSource),若存在,则 EmbeddedDatabaseConfiguration 不能被实例化

    1. @Configuration(proxyBeanMethods = false)
    2. @Conditional(EmbeddedDatabaseCondition.class)
    3. @ConditionalOnMissingBean({
    4. DataSource.class, XADataSource.class })
    5. @Import(EmbeddedDataSourceConfiguration.class)
    6. protected static class EmbeddedDatabaseConfiguration {
  1. }
  2. 通过@Import导入EmbeddedDataSourceConfiguration,它向容器中添加了一个 Spring Boot 内嵌的数据源
  3. @Configuration(proxyBeanMethods = false)
  4. @EnableConfigurationProperties(DataSourceProperties.class)
  5. public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {
  6. private ClassLoader classLoader;
  7. @Override
  8. public void setBeanClassLoader(ClassLoader classLoader) {
  9. this.classLoader = classLoader;
  10. }
  11. //向容器中添加 Spring Boot 内嵌的数据源,支持 HSQL,H2 和 DERBY 三种数据库
  12. @Bean(destroyMethod = "shutdown")
  13. public EmbeddedDatabase dataSource(DataSourceProperties properties) {
  14. //配置默认的数据源
  15. return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseConnection.get(this.classLoader).getType())
  16. .setName(properties.determineDatabaseName()).build();
  17. }
  18. }
  1. PooledDataSourceConfiguration:池化数据源配置

    通过@Conditional(PooledDataSourceCondition.class) 用来检测容器中是否已经存在池化数据源的,若存在,可以向容器中添加池化数据源。

    1. @Configuration(proxyBeanMethods = false)
    2. @Conditional(PooledDataSourceCondition.class)
    3. @ConditionalOnMissingBean({
    4. DataSource.class, XADataSource.class })
    5. @Import({
    6. DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
    7. DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
    8. DataSourceJmxConfiguration.class })
    9. protected static class PooledDataSourceConfiguration {
  1. }
  2. @Import 注解引入了 HikariTomcatDbcp2OracleUcp Generic 五个数据源配置类,它们都是 DataSourceConfiguration 的内部类,作用是向容器中添加指定的数据源
  3. @Configuration(proxyBeanMethods = false) //当前类是一个配置类;
  4. @ConditionalOnClass(HikariDataSource.class) //容器中没有用户自定义的数据源时,该配置类才会被实例化;
  5. @ConditionalOnMissingBean(DataSource.class) //必须在类路径中存在 HikariDataSource时,才会实例化。
  6. @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
  7. static class Hikari {
  8. //在配置文件中配置了 spring.datasource.type = com.zaxxer.hikari.HikariDataSource或者不配置 spring.datasource.type(即默认情况)时,Hikari 才会被实例化。
  9. @Bean
  10. @ConfigurationProperties(prefix = "spring.datasource.hikari")
  11. HikariDataSource dataSource(DataSourceProperties properties) {
  12. HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
  13. if (StringUtils.hasText(properties.getName())) {
  14. dataSource.setPoolName(properties.getName());
  15. }
  16. return dataSource;
  17. }
  18. }
  1. PooledDataSourceCondition:合并数据源条件,主要用来检测容器中是否已经存在池化数据源(PooledDataSource)。

    1. static class PooledDataSourceCondition extends AnyNestedCondition {
    2. PooledDataSourceCondition() {
    3. super(ConfigurationPhase.PARSE_CONFIGURATION);
    4. }
    5. @ConditionalOnProperty(prefix = "spring.datasource", name = "type")
    6. static class ExplicitType {
    7. }
    8. @Conditional(PooledDataSourceAvailableCondition.class)
    9. static class PooledDataSourceAvailable {
    10. }
    11. }
  2. PooledDataSourceAvailableCondition:测试支持的连接池是否可用的Condition 。

    1. static class PooledDataSourceAvailableCondition extends SpringBootCondition {
  1. @Override
  2. public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
  3. ConditionMessage.Builder message = ConditionMessage.forCondition("PooledDataSource");
  4. if (DataSourceBuilder.findType(context.getClassLoader()) != null) {
  5. return ConditionOutcome.match(message.foundExactly("supported DataSource"));
  6. }
  7. return ConditionOutcome.noMatch(message.didNotFind("supported DataSource").atAll());
  8. }
  9. }
  1. EmbeddedDatabaseCondition:检测何时可以使用嵌入式DataSource类型的Condition ,如果一个池化的DataSource可用,它总是优先于EmbeddedDatabase 。

    1. static class EmbeddedDatabaseCondition extends SpringBootCondition {
    2. //数据源 URL 属性
    3. private static final String DATASOURCE_URL_PROPERTY = "spring.datasource.url";
    4. //合并条件
    5. private final SpringBootCondition pooledCondition = new PooledDataSourceCondition();
    6. //
    7. @Override
    8. public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
    9. ConditionMessage.Builder message = ConditionMessage.forCondition("EmbeddedDataSource");
    10. if (hasDataSourceUrlProperty(context)) {
    11. return ConditionOutcome.noMatch(message.because(DATASOURCE_URL_PROPERTY + " is set"));
    12. }
    13. if (anyMatches(context, metadata, this.pooledCondition)) {
    14. return ConditionOutcome.noMatch(message.foundExactly("supported pooled data source"));
    15. }
    16. EmbeddedDatabaseType type = EmbeddedDatabaseConnection.get(context.getClassLoader()).getType();
    17. if (type == null) {
    18. return ConditionOutcome.noMatch(message.didNotFind("embedded database").atAll());
    19. }
    20. return ConditionOutcome.match(message.found("embedded database").items(type));
    21. }
    22. private boolean hasDataSourceUrlProperty(ConditionContext context) {
    23. Environment environment = context.getEnvironment();
    24. if (environment.containsProperty(DATASOURCE_URL_PROPERTY)) {
    25. try {
    26. return StringUtils.hasText(environment.getProperty(DATASOURCE_URL_PROPERTY));
    27. }
    28. catch (IllegalArgumentException ex) {
    29. // Ignore unresolvable placeholder errors
    30. }
    31. }
    32. return false;
    33. }
    34. }

发表评论

表情:
评论列表 (有 0 条评论,141人围观)

还没有评论,来说两句吧...

相关阅读