springboot 中数据源配置,连接池配置,源码剖析,如何选择连接池

springboot目录

之前讲了springboot中如何配置MySQL以及配置多数据源,参数也都配置好了,那么springboot中到底如何选择的呢?

声明:笔者使用的springboot版本是1.5.3.RELEASE

springboot自动装配的过程就不说了,直接上核心代码。

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration该类是springboot加载数据源的核心配置类。
我们去看连接池的选择:

@Configuration
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
            DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,
            DataSourceConfiguration.Generic.class })
    @SuppressWarnings("deprecation")
    protected static class PooledDataSourceConfiguration {

    }

PooledDataSourceConfiguration上面的注解包含了tomcat连接池,dbcp,dbcp2等主流连接池。到底选择哪个连接池呢?(选择不同的连接池,application.properties配置不同
一步一步往下跟:
进入PooledDataSourceCondition
进入PooledDataSourceAvailableCondition

static class PooledDataSourceAvailableCondition extends SpringBootCondition {

        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context,
                AnnotatedTypeMetadata metadata) {
            ConditionMessage.Builder message = ConditionMessage
                    .forCondition("PooledDataSource");
            if (getDataSourceClassLoader(context) != null) {
                return ConditionOutcome
                        .match(message.foundExactly("supported DataSource"));
            }
            return ConditionOutcome
                    .noMatch(message.didNotFind("supported DataSource").atAll());
        }

        /**
         * Returns the class loader for the {@link DataSource} class. Used to ensure that
         * the driver class can actually be loaded by the data source.
         * @param context the condition context
         * @return the class loader
         */
        private ClassLoader getDataSourceClassLoader(ConditionContext context) {
            Class<?> dataSourceClass = new DataSourceBuilder(context.getClassLoader())
                    .findType();/*找到源头了*/
            return (dataSourceClass == null ? null : dataSourceClass.getClassLoader());
        }

    }

进入findtype方法:

public Class<? extends DataSource> findType() {
        if (this.type != null) {
            return this.type;
        }
        for (String name : DATA_SOURCE_TYPE_NAMES) {
            try {
                return (Class<? extends DataSource>) ClassUtils.forName(name,
                        this.classLoader);
            }
            catch (Exception ex) {
                // Swallow and continue
            }
        }
        return null;
    }

里面有一个常量数组:

private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
            "org.apache.tomcat.jdbc.pool.DataSource",
            "com.zaxxer.hikari.HikariDataSource",
            "org.apache.commons.dbcp.BasicDataSource", // deprecated
            "org.apache.commons.dbcp2.BasicDataSource" };

findType()方法中遍历该数组,从前往后,加载到哪个类就使用哪个类的连接池。
可能会因为不同项目中类不同,导致使用不同的连接池,所以最好就是在这里加个断点,亲自看一下最终选定的是哪个连接池

这里写图片描述

上图可见,笔者使用的是Tomcat连接池:org.apache.tomcat.jdbc.pool.DataSource

进入org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer类,里面有init方法,是启动的时候加载的。属性文件以及datasource的配置就是在这里完成的。

@PostConstruct
    public void init() {
        if (!this.properties.isInitialize()) {
            logger.debug("Initialization disabled (not running DDL scripts)");
            return;
        }
        if (this.applicationContext.getBeanNamesForType(DataSource.class, false,
                false).length > 0) {
                //加载dataSource 类,确认使用哪个连接池,
            this.dataSource = this.applicationContext.getBean(DataSource.class);
        }
        if (this.dataSource == null) {//在这里查看DataSource的配置信息
            logger.debug("No DataSource found so not initializing");
            return;
        }
        runSchemaScripts();
    }

在这里加个断点 ,查看最终使用的哪个连接池,以及我们的配置是否生效。
这里写图片描述

好了,接下来就是去看源码org.apache.tomcat.jdbc.pool.DataSource或者官方文档,去配置参数了.
配置信息可以参考这两个类:

public class DataSourceProxy implements PoolConfiguration {
    private static final Log log = LogFactory.getLog(DataSourceProxy.class);
    //链接配置
    protected volatile ConnectionPool pool = null;
    //连接池配置
    protected volatile PoolConfiguration poolProperties = null;

    //省略代码......
}

参考文档

测试DB连接,最大等待时间,DB测试
使用druid连接池带来的坑testOnBorrow=false

猜你喜欢

转载自blog.csdn.net/fgyibupi/article/details/79748623
今日推荐