spring boot tomcat jdbc pool的属性绑定
|
下面看下spring boot tomcat jdbc pool的属性绑定代码,具体代码如下所示: spring: datasource: type: org.apache.tomcat.jdbc.pool.DataSource driver-class-name: org.postgresql.Driver url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000 username: postgres password: postgres jmx-enabled: true initial-size: 1 max-active: 5 ## when pool sweeper is enabled,extra idle connection will be closed max-idle: 5 ## when idle connection > min-idle,poolSweeper will start to close min-idle: 1 使用如上配置,最后发现initial-size,max-active,max-idle,min-idle等配置均无效,生成的tomcat jdbc datasource还是使用的默认的配置 正确配置 spring: datasource: type: org.apache.tomcat.jdbc.pool.DataSource driver-class-name: org.postgresql.Driver url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000 username: postgres password: postgres jmx-enabled: true tomcat: ## 单个数据库连接池,而且得写上tomcat的属性配置才可以生效 initial-size: 1 max-active: 5 ## when pool sweeper is enabled,extra idle connection will be closed max-idle: 5 ## when idle connection > min-idle,poolSweeper will start to close min-idle: 1 注意,这里把具体tomcat数据库连接池的配置属性放到了spring.datasource.tomcat属性下面,这样才可以生效。 源码解析
spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java
@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 {
}
DataSourceConfiguration.Tomcat
spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java
/**
* Tomcat Pool DataSource configuration.
*/
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type",havingValue = "org.apache.tomcat.jdbc.pool.DataSource",matchIfMissing = true)
static class Tomcat extends DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.tomcat")
public org.apache.tomcat.jdbc.pool.DataSource dataSource(
DataSourceProperties properties) {
org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(
properties,org.apache.tomcat.jdbc.pool.DataSource.class);
DatabaseDriver databaseDriver = DatabaseDriver
.fromJdbcUrl(properties.determineUrl());
String validationQuery = databaseDriver.getValidationQuery();
if (validationQuery != null) {
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery(validationQuery);
}
return dataSource;
}
}
可以看到这里的DataSourceProperties仅仅只有spring.datasource直接属性的配置,比如url,username,password,driverClassName。tomcat的具体属性都没有。 createDataSource
protected <T> T createDataSource(DataSourceProperties properties,Class<? extends DataSource> type) {
return (T) properties.initializeDataSourceBuilder().type(type).build();
}
直接createDataSource出来的org.apache.tomcat.jdbc.pool.DataSource的PoolProperties也是默认的配置 ConfigurationProperties 具体的魔力就在于
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java
private void postProcessBeforeInitialization(Object bean,String beanName,ConfigurationProperties annotation) {
Object target = bean;
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(
target);
factory.setPropertySources(this.propertySources);
factory.setValidator(determineValidator(bean));
// If no explicit conversion service is provided we add one so that (at least)
// comma-separated arrays of convertibles can be bound automatically
factory.setConversionService(this.conversionService == null
? getDefaultConversionService() : this.conversionService);
if (annotation != null) {
factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());
factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());
factory.setExceptionIfInvalid(annotation.exceptionIfInvalid());
factory.setIgnoreNestedProperties(annotation.ignoreNestedProperties());
if (StringUtils.hasLength(annotation.prefix())) {
factory.setTargetName(annotation.prefix());
}
}
try {
factory.bindPropertiesToTarget();
}
catch (Exception ex) {
String targetClass = ClassUtils.getShortName(target.getClass());
throw new BeanCreationException(beanName,"Could not bind properties to "
+ targetClass + " (" + getAnnotationDetails(annotation) + ")",ex);
}
}
注意,这里的annotation就是
PropertiesConfigurationFactory.bindPropertiesToTarget
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/PropertiesConfigurationFactory.java
public void bindPropertiesToTarget() throws BindException {
Assert.state(this.propertySources != null,"PropertySources should not be null");
try {
if (logger.isTraceEnabled()) {
logger.trace("Property Sources: " + this.propertySources);
}
this.hasBeenBound = true;
doBindPropertiesToTarget();
}
catch (BindException ex) {
if (this.exceptionIfInvalid) {
throw ex;
}
PropertiesConfigurationFactory.logger
.error("Failed to load Properties validation bean. "
+ "Your Properties may be invalid.",ex);
}
}
委托给doBindPropertiesToTarget方法
PropertiesConfigurationFactory.doBindPropertiesToTarget
private void doBindPropertiesToTarget() throws BindException {
RelaxedDataBinder dataBinder = (this.targetName != null
? new RelaxedDataBinder(this.target,this.targetName)
: new RelaxedDataBinder(this.target));
if (this.validator != null
&& this.validator.supports(dataBinder.getTarget().getClass())) {
dataBinder.setValidator(this.validator);
}
if (this.conversionService != null) {
dataBinder.setConversionService(this.conversionService);
}
dataBinder.setAutoGrowCollectionLimit(Integer.MAX_VALUE);
dataBinder.setIgnoreNestedProperties(this.ignoreNestedProperties);
dataBinder.setIgnoreInvalidFields(this.ignoreInvalidFields);
dataBinder.setIgnoreUnknownFields(this.ignoreUnknownFields);
customizeBinder(dataBinder);
Iterable<String> relaxedTargetNames = getRelaxedTargetNames();
Set<String> names = getNames(relaxedTargetNames);
PropertyValues propertyValues = getPropertySourcesPropertyValues(names,relaxedTargetNames);
dataBinder.bind(propertyValues);
if (this.validator != null) {
dataBinder.validate();
}
checkForBindingErrors(dataBinder);
}
这里借助RelaxedDataBinder.bind方法
getRelaxedTargetNames
private Iterable<String> getRelaxedTargetNames() {
return (this.target != null && StringUtils.hasLength(this.targetName)
? new RelaxedNames(this.targetName) : null);
}
这里new了一个RelaxedNames,可以识别多个变量的变种 RelaxedNames
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/RelaxedNames.java
private void initialize(String name,Set<String> values) {
if (values.contains(name)) {
return;
}
for (Variation variation : Variation.values()) {
for (Manipulation manipulation : Manipulation.values()) {
String result = name;
result = manipulation.apply(result);
result = variation.apply(result);
values.add(result);
initialize(result,values);
}
}
}
/**
* Name variations.
*/
enum Variation {
NONE {
@Override
public String apply(String value) {
return value;
}
},LOWERCASE {
@Override
public String apply(String value) {
return value.isEmpty() ? value : value.toLowerCase();
}
},UPPERCASE {
@Override
public String apply(String value) {
return value.isEmpty() ? value : value.toUpperCase();
}
};
public abstract String apply(String value);
}
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
