加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

spring boot tomcat jdbc pool的属性绑定

发布时间:2020-05-28 02:54:31 所属栏目:Java 来源:互联网
导读:下面看下springboottomcatjdbcpool的属性绑定代码,具体代码如下所示:spring:datasource:

下面看下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

具体的魔力就在于@ConfigurationProperties(prefix = "spring.datasource.tomcat")这段代码,它在spring容器构造好代理bean返回之前会将spring.datasource.tomcat指定的属性设置到org.apache.tomcat.jdbc.pool.DataSource

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就是@ConfigurationProperties(prefix = "spring.datasource.tomcat"),它的prefix是spring.datasource.tomcat PropertiesConfigurationFactory的targetName就是spring.datasource.tomcat

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);
 }

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读