MrRobot5 生也有涯,知也无涯

Spring Boot DataSource 知识梳理


梳理 Spring Boot 默认配置的数据库和连接池,以及自定义配置的方法

database

Spring Boot gives you defaults on all things. For example, the default database is H2.

Consequently, when you want to use any other database, you must define the connection attributes in the application.properties file.

①default

# org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection#H2
# 内嵌数据库支持 H2 Derby Hsqldb,首选 H2。
spring.datasource.url=jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver

②自定义

spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/db_example
spring.datasource.username=springuser
spring.datasource.password=ThePassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.jpa.show-sql: true

③Code Insight

/**
 * 查找最匹配的 EmbeddedDatabaseConnection
 * Spring Boot 内置EmbeddedDatabaseConnection 配置。作为 DataSourceProperties 托底配置。
 * 如果没有指定的DatabaseConnection,就会取 EmbeddedDatabaseConnection。
 * @see org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
 * @see org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection
 */
public static EmbeddedDatabaseConnection get(ClassLoader classLoader) {
	if (override != null) {
		return override;
	}
	// 按照定义顺序,遍历 H2 Derby Hsqldb
	for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection.values()) {
		// 如果存在数据库 DriverClass,就返回对应数据库的 Connection
		if (candidate != NONE && ClassUtils.isPresent(candidate.getDriverClassName(), classLoader)) {
			return candidate;
		}
	}
	return NONE;
}

DataSource

内置初始化支持 DBCP Tomcat-Pool HikariCP

We prefer HikariCP for its performance and concurrency. If HikariCP is available, we always choose it.

①default

根据 spring-boot-starter-jdbc 版本的不同,1.x 自动引入 tomcat-jdbc , 2.x 自动引入 HikariCP

②自定义

# 使用 tomcat pool
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.test-on-borrow=true

③Code Insight

static class Hikari {

	@Bean
	// dataSourcet() 执行完成后,给dataSource实例绑定特有的 properties
	@ConfigurationProperties(prefix = "spring.datasource.hikari")
	HikariDataSource dataSource(DataSourceProperties properties) {
		// new DataSource(), 并且绑定基础的属性:jdbcUrl driverClassName username password
		HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
		if (StringUtils.hasText(properties.getName())) {
			dataSource.setPoolName(properties.getName());
		}
		return dataSource;
	}

}

Beans annotated with ConfigurationProperties

如上述的用法,ConfigurationProperties 如何绑定属性,并且绑定的时机非常关键。

Spring Boot 提供 org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor 处理器,用来完成Bean 属性的绑定。

/**
 * instance 之后,进行属性绑定,后续 Initialization 能够用到这些属性。
 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
 */
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	ConfigurationProperties annotation = AnnotationUtils.findAnnotation(bean.getClass(), ConfigurationProperties.class);
	if (annotation != null) {
		postProcessBeforeInitialization(bean, beanName, annotation);
	}
	annotation = this.beans.findFactoryAnnotation(beanName, ConfigurationProperties.class);
	if (annotation != null) {
		postProcessBeforeInitialization(bean, beanName, annotation);
	}
	return bean;
}

Similar Posts

Content