天天看点

SpringBoot关于数据源的一些事

文章目录

        • SpringBoot 默认的数据源是什么?
        • DruidDataSource 是如何被加载的?
        • Failed to configure a DataSource 这个错见过吗?

SpringBoot 默认的数据源是什么?

先把目光聚焦在DataSourceAutoConfiragution(spring-boot-autoconfigure),根据SpringBoot自动装配的特性可知,

@Configuration
	@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 {

	}
           

PooledDataSourceConfiguration类会引入这么多Java Config。这里主要关注DataSourceConfiguration.Hikari

@Configuration
	@ConditionalOnClass(HikariDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type",
			havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
	static class Hikari {

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.hikari")
		public HikariDataSource dataSource(DataSourceProperties properties) {
			HikariDataSource dataSource = createDataSource(properties,
					HikariDataSource.class);
			if (StringUtils.hasText(properties.getName())) {
				dataSource.setPoolName(properties.getName());
			}
			return dataSource;
		}

	}
           

从上面的配置可以看到,只要ClassPath中存在类

HikariDataSource

且不存在

DataSource

的Bean,就会去构造HikariDataSource.

这里需要注意两点:1、入参DataSourceProperties 2、createDataSource()方法

DataSourceProperties就是我们平常配置在application.properties中属性对应的实体,例如

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.password=root
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://localhost:3306/ds0?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
           

HikariDataSource的构造过程 createDataSource

protected static <T> T createDataSource(DataSourceProperties properties,
			Class<? extends DataSource> type) {
		return (T) properties.initializeDataSourceBuilder().type(type).build();
	}
           

这里的type是前面传入的

HikariDataSource

,这里主要是使用配置中的用户名、密码、url等构造HikariDataSource实例

因此 可以说 默认SpringBoot的数据源是

HikariDataSource

DruidDataSource 是如何被加载的?

移步到DruidDataSourceAutoConfigure一看便知

@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,
    DruidStatViewServletConfiguration.class,
    DruidWebStatFilterConfiguration.class,
    DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {

    private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);

    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        LOGGER.info("Init DruidDataSource");
        return new DruidDataSourceWrapper();
    }
}
           

DruidStatProperties 这个DruidDataSource属性配置类,前缀为spring.datasource.druid

DataSourceProperties是默认数据源属性配置类,它们两者的关系是 若有些配置没有在DruidStatProperties 中找到,则尝试去DataSourceProperties找配置

Failed to configure a DataSource 这个错见过吗?

其实 这个错通常完整的描述是

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine suitable jdbc url


Action:

Consider the following:
	If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
	If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
           

通常遇到这种问题,是项目里引入了第三方数据源导致的,比如DruidDataSource,以Druid数据源为例,它需要一些自己的配置,如spring.datasource.druid.xxx

虽然引入了Druid的starter,但是默认的DataSourceAutoConfiguration也会被加载,HikariDataSource也会被创建,而创建HikariDataSource时 需要的一些属性可能没有被设置 就引发了前面说的报错

解决方式:

如要使用第三方数据源如DruidDataSource,则必须在SpringBoot启动类排除

DataSourceAutoConfiguration

,如

继续阅读