SpringBoot?DataSource數(shù)據(jù)源實現(xiàn)自動配置流程詳解
一、重點概念
1、什么是DataSource數(shù)據(jù)源
javax.sql.DataSource是由JDBC2.0 提供的接口,它負責(zé)建立與數(shù)據(jù)庫的連接,當(dāng)在應(yīng)用程序中訪問數(shù)據(jù)庫時不必編寫連接數(shù)據(jù)庫的代碼,直接引用DataSource獲取數(shù)據(jù)庫的連接對象即可。用于獲取操作數(shù)據(jù)Connection對象
2、數(shù)據(jù)庫連接池
當(dāng)我們使用數(shù)據(jù)源建立多個數(shù)據(jù)庫連接,這些數(shù)據(jù)庫連接會保存在數(shù)據(jù)庫連接池中,當(dāng)需要訪問數(shù)據(jù)庫時,只需要從數(shù)據(jù)庫連接池中獲取空閑的數(shù)據(jù)庫連接,當(dāng)程序訪問數(shù)據(jù)庫結(jié)束時,數(shù)據(jù)庫連接會放回數(shù)據(jù)庫連接池中
二、導(dǎo)入依賴
首先我們需要導(dǎo)入JDBC相關(guān)場景
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency>
然后,我們還需要導(dǎo)入數(shù)據(jù)庫的連接驅(qū)動
注意,我們要根據(jù)數(shù)據(jù)庫的版本去導(dǎo)入對應(yīng)版本的驅(qū)動
因為Spring Boot它有默認的版本仲裁,即使不聲明version也會有默認版本
所以我們可以直接修改依賴引入的版本(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>
三、分析自動配置
1、DataSourceAutoConfiguration類
從名字不難看出,這個類和數(shù)據(jù)源的自動配置有關(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() { } ...
通過分析這個自動配置類,我們可以發(fā)現(xiàn)它綁定了一個DataSourceProperties.class
配置類
@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)配置項即可
這里面有很多數(shù)據(jù)源的配置項,例如url、username等
在這個自動配置類中還有一個內(nèi)嵌的配置類PooledDataSourceConfiguration
它在容器中沒有DataSource.class
和XADataSource.class
這兩種類型的bean時才會生效
它使用@Import導(dǎo)入了針對不同數(shù)據(jù)庫類型數(shù)據(jù)源連接組件的數(shù)據(jù)源配置,這些配置僅在使用了相應(yīng)的數(shù)據(jù)源連接組件時才生效,一般開發(fā)人員只使用其中一種,所以也就只會有一個生效
@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() { } }
我們隨便點進一個它導(dǎo)入的數(shù)據(jù)源連接組件,跳轉(zhuǎn)到DataSourceConfiguration
類,可以看到我們前面自動導(dǎo)入的Hikari的相關(guān)配置如下,我們梳理一下這個類生效的條件
- 容器中存在
HikariDataSource.class
類型的bean - 沒有
DataSource.class
這個類型的bean - 系統(tǒng)配置項
spring.datasource.type
的值為com.zaxxer.hikari.HikariDataSource
或者空
這里我們介紹一下matchIfMissing
:當(dāng)配置為空時,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類
事務(wù)管理器的自動配置
3、JdbcTemplateAutoConfiguration類
這個是JdbcTemplate的自動配置,JdbcTemplate可以來對數(shù)據(jù)庫進行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ān)類代碼可知,我們可以通過修改spring.jdbc
開頭的配置來對JdbcTemplate進行配置調(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; }
然后這個自動配置類導(dǎo)入的配置類又會去操作我們前面配置好的數(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類
Jndi自動配置
5、XADataSourceAutoConfiguration類
分布式事務(wù)的自動配置
四、代碼樣例
結(jié)合上面的源碼分析,我們可以寫一個簡單的demo來進行數(shù)據(jù)庫查詢
首先我們?nèi)ハ到y(tǒng)配置文件中定義一些關(guān)于數(shù)據(jù)源的配置項
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
下面就是測試代碼
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); } }
最后測試結(jié)果如圖
到此這篇關(guān)于SpringBoot DataSource數(shù)據(jù)源實現(xiàn)自動配置流程詳解的文章就介紹到這了,更多相關(guān)SpringBoot DataSource數(shù)據(jù)源配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java通過PropertyDescriptor反射調(diào)用set和get方法
這篇文章主要為大家詳細介紹了Java通過PropertyDescriptor反射調(diào)用set和get方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03Struts1簡介和入門_動力節(jié)點Java學(xué)院整理
這篇文章主要為大家詳細介紹了Struts1簡介和入門的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09Mybatis-plus常見的坑@TableField不生效問題
這篇文章主要介紹了Mybatis-plus常見的坑@TableField不生效問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01