Spring Boot 2.1.7 数据源主动加载过程详解

打印 上一主题 下一主题

主题 773|帖子 773|积分 2319

在 Spring Boot 中,数据源的主动设置是框架中一个关键功能,本文将以 Spring Boot 2.1.7 版本为例,详细讲解在单数据源情况下数据源是如何主动加载的。我们通过源码分析,追踪整个加载流程。

1. 主动设置类的发现

Spring Boot 使用 spring.factories 机制加载主动设置类。在 org.springframework.boot.autoconfigure 包的 META-INF/spring.factories 文件中,可以找到:
  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
复制代码
此中,DataSourceAutoConfiguration 是数据源的主动设置类。

2. DataSourceAutoConfiguration 类

进入 DataSourceAutoConfiguration 类,可以看到其内部有一个静态嵌套类 PooledDataSourceConfiguration
  1. @Configuration
  2. @Conditional({PooledDataSourceCondition.class})
  3. @ConditionalOnMissingBean({DataSource.class, XADataSource.class})
  4. @Import({
  5.     DataSourceConfiguration.Hikari.class,
  6.     DataSourceConfiguration.Tomcat.class,
  7.     DataSourceConfiguration.Dbcp2.class,
  8.     DataSourceConfiguration.Generic.class,
  9.     DataSourceJmxConfiguration.class
  10. })
  11. protected static class PooledDataSourceConfiguration {
  12.     protected PooledDataSourceConfiguration() {
  13.     }
  14. }
复制代码
关键点解释:


  • @Conditional:依靠于 PooledDataSourceCondition 判断是否满足条件。
  • @ConditionalOnMissingBean:确保没有自定义的 DataSource 和 XADataSource Bean。
  • @Import:导入了 Hikari、Tomcat、Dbcp2 等数据源的设置类。

3. DataSourceConfiguration.Hikari 类

进入 DataSourceConfiguration.Hikari,这是 HikariCP 数据源的设置类(Tomcat、Dbcp2也类似):
  1. @Configuration
  2. @ConditionalOnClass({HikariDataSource.class})
  3. @ConditionalOnMissingBean({DataSource.class})
  4. @ConditionalOnProperty(
  5.     name = {"spring.datasource.type"},
  6.     havingValue = "com.zaxxer.hikari.HikariDataSource",
  7.     matchIfMissing = true
  8. )
  9. static class Hikari {
  10.     Hikari() {
  11.     }
  12.     @Bean
  13.     @ConfigurationProperties(prefix = "spring.datasource.hikari")
  14.     public HikariDataSource dataSource(DataSourceProperties properties) {
  15.         HikariDataSource dataSource = (HikariDataSource)
  16.             DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
  17.         
  18.         if (StringUtils.hasText(properties.getName())) {
  19.             dataSource.setPoolName(properties.getName());
  20.         }
  21.         return dataSource;
  22.     }
  23. }
复制代码
关键点解释:


  • @ConditionalOnClass:确保 HikariDataSource 在类路径中存在,即有在pom文件中直接或间接的导入HikariCP依靠。
  • @ConditionalOnMissingBean:如果没有本身定义其他 DataSource,则会加载此设置。
  • @ConditionalOnProperty:当在application.yml或application.properties设置文件中 spring.datasource.type 的值是 HikariDataSource 或未定义时,匹配条件创建,使用 Hikari 数据源。
    @ConditionalOnProperty具体用法可以看这篇:@ConditionalOnProperty

4. createDataSource 方法

进入 DataSourceConfiguration.createDataSource 方法:
  1. protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {
  2.    return properties.initializeDataSourceBuilder().type(type).build();
  3. }
复制代码
initializeDataSourceBuilder 方法采用了制作者模式对DataSourceBuilder对象举行了属性赋值。具体源码比较简单,各人可以本身点进去看看,要是看不懂可以先去看看制作者模式的文章。
制作者模式可以看这篇文章:制作者模式

5. DataSourceBuilder 的 build 方法

进入build 方法:
  1. public T build() {
  2.     Class<? extends DataSource> type = this.getType();
  3.     DataSource result = (DataSource)BeanUtils.instantiateClass(type);
  4.     this.maybeGetDriverClassName();
  5.     this.bind(result);
  6.     return result;
  7. }
复制代码
关键步调:


  • getType 方法:获取数据源的类型。
  • BeanUtils.instantiateClass(type):通过反射实例化数据源对象。
  • bind(result):将设置信息绑定到数据源对象。

6. getType 方法与默认数据源

在 getType 方法中,当 type 为 null 时,进入 findType 方法:
  1. private Class<? extends DataSource> getType() {
  2.     Class<? extends DataSource> type = this.type != null
  3.         ? this.type
  4.         : findType(this.classLoader);
  5.     if (type != null) {
  6.         return type;
  7.     } else {
  8.         throw new IllegalStateException("No supported DataSource type found");
  9.     }
  10. }
复制代码
findType 方法的实现:

  1. public static Class<? extends DataSource> findType(ClassLoader classLoader) {
  2.     String[] var1 = DATA_SOURCE_TYPE_NAMES;
  3.     for (String name : var1) {
  4.         try {
  5.             return ClassUtils.forName(name, classLoader);
  6.         } catch (Exception ignored) {
  7.         }
  8.     }
  9.     return null;
  10. }
  11. private static final String[] DATA_SOURCE_TYPE_NAMES = new String[]{
  12.     "com.zaxxer.hikari.HikariDataSource",
  13.     "org.apache.tomcat.jdbc.pool.DataSource",
  14.     "org.apache.commons.dbcp2.BasicDataSource"
  15. };
复制代码
关键点解释:


  • 默认数据源顺序

    • com.zaxxer.hikari.HikariDataSource(HikariCP)
    • org.apache.tomcat.jdbc.pool.DataSource(Tomcat 数据源)
    • org.apache.commons.dbcp2.BasicDataSource(DBCP2 数据源)

  • 当 type 为 null 时,会按照顺序加载第一个可用的数据源,即 HikariCP

7. 总结

通过以上分析,可以得出 Spring Boot 数据源主动加载的焦点流程:

  • 加载主动设置类:通过 spring.factories 加载 DataSourceAutoConfiguration。
  • 匹配数据源设置:判断条件,导入 Hikari、Tomcat、Dbcp2 等数据源设置类。
  • 优先选择 HikariCP:如果未指定 spring.datasource.type,默认会选择 HikariCP 作为数据源。
  • 数据源初始化:通过 DataSourceBuilder 使用责任链模式构建数据源对象。

8. 源码阅读发起

在阅读 Spring Boot 源码时,版本差异大概会导致设置逻辑有所差别,因此:

  • 尽量选择与项目中一致的 Spring Boot 版本。
  • 使用调试工具,逐步跟踪代码执行流程,理解主动设置的细节。

希望本文能帮助各人更好地理解 Spring Boot 2.1.7 数据源主动加载的过程,也接待各人在评论区留言,一起交换学习!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用多少眼泪才能让你相信

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表