alibaba / alibaba/druid

当使用starter配置多数据源时,ConfigurationProperties的rebinder事件会导致异常

Open
#2,178 4 comments 1 reaction 0 assignees View on GitHub
Dominant language
Java
Stars
28.2k
Forks
8.6k
PR merge metrics
No merged PRs in 30d

Description

#### 环境版本:
- druid-spring-boot-starter: 1.1.6
- spring-boot:1.5.9.RELEASE

#### 复现方法
##### 前提
配置多数据源: spring.datasource.druid.*的默认配置与spring.datasource.druid.XXX.*的配置不一致,并且是使用下面ConfigurationProperties的配置方式来配置时
```java
@Bean
@ConfigurationProperties("spring.datasource.druid.two")
public DataSource dataSourceTwo(){
return DruidDataSourceBuilder.create().build();
}
```

##### 触发原因
当该DataSource已经初始化一次之后,如果Spring再次触发EnvironmentChangeEvent事件,会导致使用所有标注了@ConfigurationProperties的DruidDataSourceWrapper重新做参数绑定。这个时候,根据spring的规则,会先绑定DruidDataSourceWrapper对象class上标注的@ConfigurationProperties,而这个参数和factory方法上绑定的参数不一致,这时候就会触发DruidDataSource内对已经inited之后修改属性值抛出的UnsupportOperationException

##### 异常示例
```
Caused by: org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 1 errors
Field error in object 'spring.datasource.druid' on field 'url': rejected value [jdbc:mysql://XXXXXX]; codes [methodInvocation.spring.datasource.druid.url,methodInvocation.url,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.datasource.druid.url,url]; arguments []; default message [url]]; default message [Property 'url' threw exception; nested exception is java.lang.UnsupportedOperationException]
at org.springframework.boot.bind.PropertiesConfigurationFactory.checkForBindingErrors(PropertiesConfigurationFactory.java:359)
at org.springframework.boot.bind.PropertiesConfigurationFactory.doBindPropertiesToTarget(PropertiesConfigurationFactory.java:276)
at org.springframework.boot.bind.PropertiesConfigurationFactory.bindPropertiesToTarget(PropertiesConfigurationFactory.java:240)
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:330)
... 27 more
```

Contributor guide

Open the contributing guide

Research direction

Start with the ConfigurationPropertiesBindingPostProcessor and DruidDataSourceWrapper behavior described in the stack trace, then reproduce the issue using two differently configured data sources and an EnvironmentChangeEvent. Done means rebinding no longer raises UnsupportedOperationException after a data source has been initialized.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring-boot
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.