• 大三学习进度11


    DataSourceAutoConfiguration

    我们知道,Spring Boot 中几乎所有的默认配置都是通过配置类 XxxAutoConfiguration 进行配置的,Spring Boot 数据源也不例外,它的自动配置类是:DataSourceAutoConfiguration。

    DataSourceAutoConfiguration 中共包括以下 5 个内部静态类:

    EmbeddedDatabaseCondition

    PooledDataSourceAvailableCondition

    PooledDataSourceCondition

    PooledDataSourceConfiguration(池化数据源自动配置类)

    EmbeddedDatabaseConfiguration(内嵌数据源自动配置类)

    其中,PooledDataSourceConfiguration 和 EmbeddedDatabaseConfiguration 为使用了 @Configuration 注解的自动配置类,其余 3 个为限制条件类。

    EmbeddedDatabaseConfiguration 

    顾名思义,EmbeddedDatabaseConfiguration 是内嵌数据源的自动配置类,该类中并没有任何的方法实现,它的主要功能都是通过 @Import 注解引入 EmbeddedDataSourceConfiguration 类来实现的。

    @Import({EmbeddedDataSourceConfiguration.class})

    EmbeddedDataSourceConfiguration 向容器中添加了一个 Spring Boot 内嵌的数据源,该数据源支持 HSQL,H2 和 DERBY 三种数据库,其部分代码如下。 

    @Configuration(

        proxyBeanMethods = false

    )

    @EnableConfigurationProperties({DataSourceProperties.class})

    public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {

        private ClassLoader classLoader;

        public EmbeddedDataSourceConfiguration() {

        }

        public void setBeanClassLoader(ClassLoader classLoader) {

            this.classLoader = classLoader;

        }

        //向容器中添加 Spring Boot 内嵌的数据源

        @Bean(

            destroyMethod = "shutdown"

        )

        public EmbeddedDatabase dataSource(DataSourceProperties properties) {

            return (new EmbeddedDatabaseBuilder()).setType(EmbeddedDatabaseConnection.get(this.classLoader).getType()).setName(properties.determineDatabaseName()).build();

        }

    }

    通过上面的分析,我们知道自动配置类 EmbeddedDatabaseConfiguration 的作用是向容器中添加一个内嵌的数据源(DataSource),但这是有条件限制的。

    在 EmbeddedDatabaseConfiguration 类上还使用一个 @Conditional 注解,该注解使用了 DataSourceAutoConfiguration 的内部限制条件类 EmbeddedDatabaseCondition 来进行条件判断。

    @Conditional({DataSourceAutoConfiguration.EmbeddedDatabaseCondition.class})

    EmbeddedDatabaseCondition 主要用来检测容器中是否已经存在池化数据源(PooledDataSource)。若容器中存在池化数据源时,则 EmbeddedDatabaseConfiguration 不能被实例化。只有当容器中不存在池化数据源时,EmbeddedDatabaseConfiguration 才能被实例化,才能向容器中添加内嵌数据源(EmbeddedDataSource)。

    PooledDataSourceConfiguration

    PooledDataSourceConfiguration 是池化数据源的自动配置类,该类上使用了一个 @Conditional 注解,该注解使用了 DataSourceAutoConfiguration 的内部限制条件类 PooledDataSourceCondition 来进行条件判断。

    @Conditional({DataSourceAutoConfiguration.PooledDataSourceCondition.class})

    PooledDataSourceCondition 与 EmbeddedDatabaseCondition 一样,也是用来检测容器中是否已经存在池化数据源的,但不同的是,PooledDataSourceConfiguration 是只有当容器中存在池化数据源时, 才可以被实例化,才可以向容器中添加池化数据源。

    与 EmbeddedDatabaseConfiguration 一样,PooledDataSourceConfiguration  类中也没有任何的方法实现,它的所有功能都是通过 @Import 注解引入其他的类实现的。

    @Import({Hikari.class, Tomcat.class, Dbcp2.class, OracleUcp.class, Generic.class, DataSourceJmxConfiguration.class})

    PooledDataSourceConfiguration  通过 @Import 注解引入了 Hikari、Tomcat、Dbcp2、OracleUcp 和 Generic 五个数据源配置类,它们都是 DataSourceConfiguration 的内部类,且它们的功能类似,都是向容器中添加指定的数据源。

    下面我们以 Hikari 为例进行分析,Hikari 的源码如下。

    @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;

        }

    }

    在 Hikari 类中,主要使用以下注解:

    @Configuration:表示当前类是一个配置类;

     @ConditionalOnMissingBean({DataSource.class}):表示容器中没有用户自定义的数据源时,该配置类才会被实例化;

    @ConditionalOnClass({HikariDataSource.class}) :表示必须在类路径中存在 HikariDataSource 类时,Hikari 才会实例化。而 HikariDataSource 类是由 spring- boot-starter-jdbc 默认将其引入的,因此只要我们在 pom.xml 中引入了该 starter, Hikari 就会被实例化(这也是 Spring Boot 2.x 默认使用 HikariCP 作为其数据源的原因)。;

    @ConditionalOnProperty( name = {"spring.datasource.type"},havingValue = "com.zaxxer.hikari.HikariDataSource",matchIfMissing = true): 表示当 Spring Boot 配置文件中,配置了 spring.datasource.type = com.zaxxer.hikari.HikariDataSource(明确指定使用 Hikari 数据源)或者不配置 spring.datasource.type(即默认情况)时,Hikari 才会被实例化。

    Hikari 类通过 @Bean 注解向容器中添加了 HikariDataSource 组件,该组件的实例对象是通过调用 DataSourceConfiguration 的 createDataSource() 方法得到的,代码如下。

    @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;

    }

    在 createDataSource() 方法中,调用 DataSourceProperties 的 initializeDataSourceBuilder() 来初始化 DataSourceBuilder,源码如下。

    protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {

        return properties.initializeDataSourceBuilder().type(type).build();

    }

    initializeDataSourceBuilder() 方法通过调用 DataSourceBuilder 的 create() 方法创建 DataSourceBuilder 对象,并根据 Spring Boot 的配置文件(application.properties/yml)中的配置,依次设置数据源类型、驱动类名、连接 url、 用户名和密码等信息。

    纯文本复制

    public DataSourceBuilder<?> initializeDataSourceBuilder() {

        return DataSourceBuilder.create(this.getClassLoader()).type(this.getType()).

              driverClassName(this.determineDriverClassName()).url(this.determineUrl()).username(this.determineUsername()).password(this.determinePassword());

    }

  • 相关阅读:
    WCF异常管理—不要在using语句中调用WCF服务(z)
    正则表达式
    nginx汇总(z)
    WCF编解码实现
    zTree -- jQuery 树插件
    C# 程序异常管理方案
    WPF剪切板问题-OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))
    乘法逆元
    二叉树后序遍历(非递归)
    P1892 [BOI2003]团伙
  • 原文地址:https://www.cnblogs.com/hhw12345/p/14157527.html
Copyright © 2020-2023  润新知