SpringBoot?DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程詳解
一、重點(diǎn)概念
1、什么是DataSource數(shù)據(jù)源
javax.sql.DataSource是由JDBC2.0 提供的接口,它負(fù)責(zé)建立與數(shù)據(jù)庫(kù)的連接,當(dāng)在應(yīng)用程序中訪問(wèn)數(shù)據(jù)庫(kù)時(shí)不必編寫(xiě)連接數(shù)據(jù)庫(kù)的代碼,直接引用DataSource獲取數(shù)據(jù)庫(kù)的連接對(duì)象即可。用于獲取操作數(shù)據(jù)Connection對(duì)象
2、數(shù)據(jù)庫(kù)連接池
當(dāng)我們使用數(shù)據(jù)源建立多個(gè)數(shù)據(jù)庫(kù)連接,這些數(shù)據(jù)庫(kù)連接會(huì)保存在數(shù)據(jù)庫(kù)連接池中,當(dāng)需要訪問(wèn)數(shù)據(jù)庫(kù)時(shí),只需要從數(shù)據(jù)庫(kù)連接池中獲取空閑的數(shù)據(jù)庫(kù)連接,當(dāng)程序訪問(wèn)數(shù)據(jù)庫(kù)結(jié)束時(shí),數(shù)據(jù)庫(kù)連接會(huì)放回?cái)?shù)據(jù)庫(kù)連接池中
二、導(dǎo)入依賴
首先我們需要導(dǎo)入JDBC相關(guān)場(chǎng)景
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency>

然后,我們還需要導(dǎo)入數(shù)據(jù)庫(kù)的連接驅(qū)動(dòng)
注意,我們要根據(jù)數(shù)據(jù)庫(kù)的版本去導(dǎo)入對(duì)應(yīng)版本的驅(qū)動(dòng)
因?yàn)镾pring Boot它有默認(rèn)的版本仲裁,即使不聲明version也會(huì)有默認(rèn)版本
所以我們可以直接修改依賴引入的版本(maven的就近依賴原則)或者在properties屬性中重新聲明版本(maven的屬性的就近優(yōu)先原則,下面使用的就是這種方式)
<properties>
<mysql.version>5.1.49</mysql.version>
</properties>
...
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
三、分析自動(dòng)配置
1、DataSourceAutoConfiguration類(lèi)
從名字不難看出,這個(gè)類(lèi)和數(shù)據(jù)源的自動(dòng)配置有關(guān)
@AutoConfiguration(
before = {SqlInitializationAutoConfiguration.class}
)
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(
type = {"io.r2dbc.spi.ConnectionFactory"}
)
@EnableConfigurationProperties({DataSourceProperties.class})
@Import({DataSourcePoolMetadataProvidersConfiguration.class})
public class DataSourceAutoConfiguration {
public DataSourceAutoConfiguration() {
}
...
通過(guò)分析這個(gè)自動(dòng)配置類(lèi),我們可以發(fā)現(xiàn)它綁定了一個(gè)DataSourceProperties.class配置類(lèi)
@ConfigurationProperties(
prefix = "spring.datasource"
)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
private ClassLoader classLoader;
private boolean generateUniqueName = true;
private String name;
private Class<? extends DataSource> type;
private String driverClassName;
private String url;
private String username;
private String password;
private String jndiName;
private EmbeddedDatabaseConnection embeddedDatabaseConnection;
private DataSourceProperties.Xa xa = new DataSourceProperties.Xa();
private String uniqueName;
...
我們發(fā)現(xiàn)想要修改數(shù)據(jù)源相關(guān)的配置,只需要調(diào)整spring.datasource相關(guān)配置項(xiàng)即可
這里面有很多數(shù)據(jù)源的配置項(xiàng),例如url、username等
在這個(gè)自動(dòng)配置類(lèi)中還有一個(gè)內(nèi)嵌的配置類(lèi)PooledDataSourceConfiguration
它在容器中沒(méi)有DataSource.class和XADataSource.class這兩種類(lèi)型的bean時(shí)才會(huì)生效
它使用@Import導(dǎo)入了針對(duì)不同數(shù)據(jù)庫(kù)類(lèi)型數(shù)據(jù)源連接組件的數(shù)據(jù)源配置,這些配置僅在使用了相應(yīng)的數(shù)據(jù)源連接組件時(shí)才生效,一般開(kāi)發(fā)人員只使用其中一種,所以也就只會(huì)有一個(gè)生效
@Configuration(
proxyBeanMethods = false
)
@Conditional({DataSourceAutoConfiguration.PooledDataSourceCondition.class})
@ConditionalOnMissingBean({DataSource.class, XADataSource.class})
@Import({Hikari.class, Tomcat.class, Dbcp2.class, OracleUcp.class, Generic.class, DataSourceJmxConfiguration.class})
protected static class PooledDataSourceConfiguration {
protected PooledDataSourceConfiguration() {
}
}
我們隨便點(diǎn)進(jìn)一個(gè)它導(dǎo)入的數(shù)據(jù)源連接組件,跳轉(zhuǎn)到DataSourceConfiguration類(lèi),可以看到我們前面自動(dòng)導(dǎo)入的Hikari的相關(guān)配置如下,我們梳理一下這個(gè)類(lèi)生效的條件
- 容器中存在
HikariDataSource.class類(lèi)型的bean - 沒(méi)有
DataSource.class這個(gè)類(lèi)型的bean - 系統(tǒng)配置項(xiàng)
spring.datasource.type的值為com.zaxxer.hikari.HikariDataSource或者空
這里我們介紹一下matchIfMissing:當(dāng)配置為空時(shí),matchIfMissing為true,配置生效
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({HikariDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "com.zaxxer.hikari.HikariDataSource",
matchIfMissing = true
)
static class Hikari {
Hikari() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.hikari"
)
HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
上述條件滿足,所以底層配置好的連接池是:HikariDataSource
2、DataSourceTransactionManagerAutoConfiguration類(lèi)
事務(wù)管理器的自動(dòng)配置
3、JdbcTemplateAutoConfiguration類(lèi)
這個(gè)是JdbcTemplate的自動(dòng)配置,JdbcTemplate可以來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行crud
@AutoConfiguration(
after = {DataSourceAutoConfiguration.class}
)
@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({JdbcProperties.class})
@Import({DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class})
public class JdbcTemplateAutoConfiguration {
public JdbcTemplateAutoConfiguration() {
}
}
通過(guò)分析該自動(dòng)配置類(lèi)的配置綁定相關(guān)類(lèi)代碼可知,我們可以通過(guò)修改spring.jdbc開(kāi)頭的配置來(lái)對(duì)JdbcTemplate進(jìn)行配置調(diào)整
@ConfigurationProperties(
prefix = "spring.jdbc"
)
public class JdbcProperties {
private final JdbcProperties.Template template = new JdbcProperties.Template();
public JdbcProperties() {
}
public JdbcProperties.Template getTemplate() {
return this.template;
}然后這個(gè)自動(dòng)配置類(lèi)導(dǎo)入的配置類(lèi)又會(huì)去操作我們前面配置好的數(shù)據(jù)源
也就是下方jdbcTemplate()方法中的dataSource參數(shù)
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnMissingBean({JdbcOperations.class})
class JdbcTemplateConfiguration {
JdbcTemplateConfiguration() {
}
@Bean
@Primary
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Template template = properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int)template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
}4、JndiDataSourceAutoConfiguration類(lèi)
Jndi自動(dòng)配置
5、XADataSourceAutoConfiguration類(lèi)
分布式事務(wù)的自動(dòng)配置
四、代碼樣例
結(jié)合上面的源碼分析,我們可以寫(xiě)一個(gè)簡(jiǎn)單的demo來(lái)進(jìn)行數(shù)據(jù)庫(kù)查詢
首先我們?nèi)ハ到y(tǒng)配置文件中定義一些關(guān)于數(shù)據(jù)源的配置項(xiàng)
spring:
datasource:
url: jdbc:mysql://localhost:3306/decade_test?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
下面就是測(cè)試代碼
package com.decade;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
@SpringBootTest
@Slf4j
class SpringbootWebApplicationTests {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
void contextLoads() {
final Long count = jdbcTemplate.queryForObject("select count(*) from t_decade_user", Long.class);
log.info("該表中數(shù)據(jù)總數(shù)為{}", count);
}
}
最后測(cè)試結(jié)果如圖

到此這篇關(guān)于SpringBoot DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程詳解的文章就介紹到這了,更多相關(guān)SpringBoot DataSource數(shù)據(jù)源配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jenkins和sonar實(shí)現(xiàn)代碼檢測(cè)過(guò)程詳解
這篇文章主要介紹了jenkins和sonar實(shí)現(xiàn)代碼檢測(cè)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
Java平臺(tái)調(diào)試體系原理分析和實(shí)踐整理 遠(yuǎn)程Debug
這篇文章主要介紹了Java平臺(tái)調(diào)試體系原理分析和實(shí)踐整理 遠(yuǎn)程Debug,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
C# 數(shù)據(jù)類(lèi)型轉(zhuǎn)換
這篇文章主要講解C語(yǔ)言中基本數(shù)據(jù)類(lèi)型、字符串與其它數(shù)據(jù)類(lèi)型以及常見(jiàn)的日期類(lèi)型的轉(zhuǎn)換,希望能給大家做一個(gè)參考。希望能夠給你帶來(lái)幫助2021-07-07
java實(shí)現(xiàn)簡(jiǎn)單的俄羅斯方塊
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的俄羅斯方塊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
使用FeignClient調(diào)用POST表單Body內(nèi)沒(méi)有參數(shù)問(wèn)題
這篇文章主要介紹了使用FeignClient調(diào)用POST表單Body內(nèi)沒(méi)有參數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBoot和Vue項(xiàng)目服務(wù)器發(fā)布流程分享
本文詳細(xì)介紹了如何將SpringBoot和Vue項(xiàng)目發(fā)布到阿里云ECS服務(wù)器上的步驟,包括準(zhǔn)備服務(wù)器、安裝寶塔、配置數(shù)據(jù)庫(kù)、打包項(xiàng)目、上傳文件、設(shè)置端口、安裝軟件和注冊(cè)網(wǎng)站等2025-02-02

