由springboot默认数据库连接池学习到的内容
springboot在2.x之后默认数据库连接池为Hikari
那么在springboot是如何设置默认数据库连接池的呢?
通过查询资料得知,springboot默认设置数据库连接池的原理为DataSourceAutoConfiguration
此源码为:
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.jdbc;
@SuppressWarnings("deprecation")
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@AutoConfigureBefore(SqlInitializationAutoConfiguration.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.InitializationSpecificCredentialsDataSourceInitializationConfiguration.class,
DataSourceInitializationConfiguration.SharedCredentialsDataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
/**
* {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
* is set or {@link PooledDataSourceAvailableCondition} applies.
*/
static class PooledDataSourceCondition extends AnyNestedCondition {
PooledDataSourceCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
static class ExplicitType {
}
@Conditional(PooledDataSourceAvailableCondition.class)
static class PooledDataSourceAvailable {
}
}
/**
* {@link Condition} to test if a supported connection pool is available.
*/
static class PooledDataSourceAvailableCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("PooledDataSource");
if (DataSourceBuilder.findType(context.getClassLoader()) != null) {
return ConditionOutcome.match(message.foundExactly("supported DataSource"));
}
return ConditionOutcome.noMatch(message.didNotFind("supported DataSource").atAll());
}
}
/**
* {@link Condition} to detect when an embedded {@link DataSource} type can be used.
* If a pooled {@link DataSource} is available, it will always be preferred to an
* {@code EmbeddedDatabase}.
*/
static class EmbeddedDatabaseCondition extends SpringBootCondition {
private static final String DATASOURCE_URL_PROPERTY = "spring.datasource.url";
private final SpringBootCondition pooledCondition = new PooledDataSourceCondition();
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("EmbeddedDataSource");
if (hasDataSourceUrlProperty(context)) {
return ConditionOutcome.noMatch(message.because(DATASOURCE_URL_PROPERTY + " is set"));
}
if (anyMatches(context, metadata, this.pooledCondition)) {
return ConditionOutcome.noMatch(message.foundExactly("supported pooled data source"));
}
EmbeddedDatabaseType type = EmbeddedDatabaseConnection.get(context.getClassLoader()).getType();
if (type == null) {
return ConditionOutcome.noMatch(message.didNotFind("embedded database").atAll());
}
return ConditionOutcome.match(message.found("embedded database").items(type));
}
private boolean hasDataSourceUrlProperty(ConditionContext context) {
Environment environment = context.getEnvironment();
if (environment.containsProperty(DATASOURCE_URL_PROPERTY)) {
try {
return StringUtils.hasText(environment.getProperty(DATASOURCE_URL_PROPERTY));
}
catch (IllegalArgumentException ex) {
// Ignore unresolvable placeholder errors
}
}
return false;
}
}
}
在阅读源码的过程中,对于几个注解比较关注
首先是:
@Configuration(proxyBeanMethods = false)
以前在写一些配置类的时候,经常使用@Configuration注解,这里加了一个属性的作用是什么?
其实通过名字就能大概了解,proxyBeanMethods设置为FALSE时,不会代理@Bean方法,也就是说,通过@Bean注解标记的方法为普通方法,不会存在bean的生命周期
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
conditional->有条件的
这里的作用是当容器中存在DataSource.class, EmbeddedDatabaseType.class的时候,被该注解标记的类才会被注入
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
当不存在参数中bean的时候,才会初始化
@AutoConfigureBefore(SqlInitializationAutoConfiguration.class)
被此注解标记的class会在参数中class初始化之前初始化
@Import(EmbeddedDataSourceConfiguration.class)
该注解的功能类似于@Bean注解,但是比@Bean注解更加快速
它可以将一个普通类注入到IOC容器中,进而可以使用@Autowirde等方式作为依赖注入普通类
还有有需要注意的地方是通过此方法注入的类的bean name为全类名
进而还有两种方法可以对该方法做一些自定义
@Conditional(PooledDataSourceCondition.class)
这是一个条件注解,被该注解标记的类需要满足参数中类的match方法才能被初始化,参数需要继承Condition类