- [x] I have searched the [issues](https://github.com/apache/dubbo/issues) of 
this repository and believe that this is not a duplicate.
- [x] I have checked the 
[FAQ](https://github.com/apache/dubbo/blob/master/FAQ.md) of this repository 
and believe that this is not a duplicate.

### Environment

* Dubbo version: 2.6.5/2.7.4.x
* Operating System version: OSX 10.x
* Java version: 1.8

在配置 dubbo.provider.token 后,有时 dubbo url 中 default.token 的值会变成 false,而非配置的 
token。原因是 getMethods()、getDeclaredMethods() 不保证顺序,导致属性绑定失败。

Spring Boot 中,dubbo 会注入多个beanPostProcessor,在 postProcessBeforeInitialization 
阶段,利用 dubboConfigBinder 对 dubbo 相关的 XxxConfig bean 进行属性绑定。如下图所示, ProviderConfig 
类是一个 bean

![image](https://user-images.githubusercontent.com/9402727/72245934-99803a80-362c-11ea-80fe-bf6fba7d190c.png)


dubboConfigBinder 在 boot 项目中,默认的实现是 RelaxedDubboConfigBinder,具体实现方式是使用 Binder 
类,此处可看源码。

绑定属性过程中,利用 JavaBeanBinder$Bean 缓存相关类属性的 getter、setter 方法。 

```java
private final Map<String, BeanProperty> properties = new LinkedHashMap<>();

Bean(ResolvableType resolvableType, Class<?> type) {
     this.resolvableType = resolvableType;
     this.type = type;
     putProperties(type);
}
private void putProperties(Class<?> type) {
     while (type != null && !Object.class.equals(type)) {

        // getDeclaredMethods() 返回方法顺序的具有不确定性
        for (Method method : type.getDeclaredMethods()) {
                if (isCandidate(method)) {
                    addMethod(method);
                }
        }
        for (Field field : type.getDeclaredFields()) {
                addField(field);
        }
        type = type.getSuperclass();
     }
}

```

由于 getDeclaredMethods() 返回方法顺序的不确定性,AbstractServiceConfig 存在两个 
setToken(boolean) 和 setToken(string),
因此当 setToken(boolean) 顺序靠前时,因为方法参数类型不满足,就无法绑定。

![image](https://user-images.githubusercontent.com/9402727/72246166-1c08fa00-362d-11ea-97cc-60c8786c9a6f.png)



以下为 setToken(string) 顺序靠前时,正确的绑定内容

![image](https://user-images.githubusercontent.com/9402727/72246135-101d3800-362d-11ea-9834-41ae87c60152.png)



在之后运行到触发 ContextRefreshedEvent 事件后,ServiceBean 执行 export() 方法,其中会填充 provider 
的属性。调用栈如下。

```
ServieBean#export()
 |- doExport()
   |- checkDefault()
     |- AbstractConfig.appendProperties(provider)
```

在 appendProperties 的实现中,getMethods 返回的方法顺序,也是 setToken(boolean) 优先。

![image](https://user-images.githubusercontent.com/9402727/72245934-99803a80-362c-11ea-80fe-bf6fba7d190c.png)



通过反射将属性注入 ProviderConfig,在注入之前,会通过 getter 方法判断属性是否已经设置,如果在前一步 Spring 
的属性绑定中是正确的,因为 token 已经有值,则不会运行的注入以下代码。

```java
// AbstractConfig.appendProperties(provider)
if (value != null && value.length() > 0) {
    method.invoke(config, new 
Object[]{convertPrimitive(method.getParameterTypes()[0], value)});
}
```

此处注入时,因为此处的方法是 setToken(boolean)。,convertPrimitive 会将 string 类型的 token 转换的目标的 
boolean 类型,Boolean.valueOf 方法就会将我们填写的 string 类型转换为 false 了。

以上就是 default.token=false 的原因


[ Full content available at: https://github.com/apache/dubbo/issues/5645 ]
This message was relayed via gitbox.apache.org for 
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to