上一篇讲用法:https://blog.csdn.net/qq_32868023/article/details/123390627
.properties到Bean的属性绑定是在Bean的实例化阶段由ConfigurationPropertiesBindingPostProcessor处理Bean实现的。首先介绍@EnableConfigurationProperties和@ConfigurationPropertiesScan注解输入注册Bean的,然后介绍ConfigurationPropertiesBindingPostProcessor到Binder的调用链路、属性绑定涉及到的重要的类,最后介绍属性绑定核心类Binder。
@EnableConfigurationProperties通过import EnableConfigurationPropertiesRegistrar这个类来注册Bean,EnableConfigurationPropertiesRegistrar是一个importBeanDefinitionRegistrar,看一下registerBeanDefinitions
public void registerBeanDefinitions(Annotationmetadata metadata, BeanDefinitionRegistry registry) {
registerInfrastructureBeans(registry);
registerMethodValidationExcludeFilter(registry);
ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
getTypes(metadata).forEach(beanRegistrar::register);
}
这里面做了两个事情
1、registerInfrastructureBeans注册了一些基础设施
static void registerInfrastructureBeans(BeanDefinitionRegistry registry) {
ConfigurationPropertiesBindingPostProcessor.register(registry);
BoundConfigurationProperties.register(registry);
}
其实就是注册了ConfigurationPropertiesBindingPostProcessor和BoundConfigurationProperties,ConfigurationPropertiesBindingPostProcessor会在bean实例化阶段进行属性绑定;BoundConfigurationProperties作用后面介绍
为什么@Bean+@Component方式时,beanFactory里也会存在ConfigurationPropertiesBindingPostProcessor?
因为有ConfigurationPropertiesAutoConfiguration自动配置类,通过@EnableConfigurationProperties注册了ConfigurationPropertiesBindingPostProcessor
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
public class ConfigurationPropertiesAutoConfiguration {
}
2、new了一个ConfigurationPropertiesBeanRegistrar,将@EnableConfigurationProperties指定的类注册到beanFactory,看一下bean注册过程
final class ConfigurationPropertiesBeanRegistrar {
void register(Class> type) {
MergedAnnotation annotation = MergedAnnotations
.from(type, SearchStrategy.TYPE_HIERARCHY).get(ConfigurationProperties.class);
register(type, annotation);
}
void register(Class> type, MergedAnnotation annotation) {
String name = getName(type, annotation);
if (!containsBeanDefinition(name)) {
registerBeanDefinition(name, type, annotation);
}
}
private void registerBeanDefinition(String beanName, Class> type,
MergedAnnotation annotation) {
Assert.state(annotation.isPresent(), () -> "No " + ConfigurationProperties.class.getSimpleName()
+ " annotation found on '" + type.getName() + "'.");
this.registry.registerBeanDefinition(beanName, createBeanDefinition(beanName, type));
}
}
其实就是创建了BeanDefinition,注册到BeanFactory里,beanName逻辑就是prefix-类全限定名,如下
private String getName(Class> type, MergedAnnotationannotation) { String prefix = annotation.isPresent() ? annotation.getString("prefix") : ""; return (StringUtils.hasText(prefix) ? prefix + "-" + type.getName() : type.getName()); }
BeanDefinition的创建逻辑,如果bindMethod == BindMethod.VALUE_OBJECT,提供一个InstanceSupplier,这里面调用了Binder#bindOrCreate来绑定bean的属性,这种情况下ConfigurationPropertiesBindingPostProcessor将不会处理这个bean
private BeanDefinition createBeanDefinition(String beanName, Class> type) {
BindMethod bindMethod = BindMethod.forType(type);
RootBeanDefinition definition = new RootBeanDefinition(type);
definition.setAttribute(BindMethod.class.getName(), bindMethod);
if (bindMethod == BindMethod.VALUE_OBJECT) {
definition.setInstanceSupplier(() -> createvalueObject(beanName, type));
}
return definition;
}
private Object createvalueObject(String beanName, Class> beanType) {
ConfigurationPropertiesBean bean = ConfigurationPropertiesBean.forValueObject(beanType, beanName);
ConfigurationPropertiesBinder binder = ConfigurationPropertiesBinder.get(this.beanFactory);
try {
return binder.bindOrCreate(bean);
}
catch (Exception ex) {
throw new ConfigurationPropertiesBindException(bean, ex);
}
}
BindMethod是什么呢?
public enum BindMethod {
JAVA_BEAN,
VALUE_OBJECT;
static BindMethod forType(Class> type) {
return (ConfigurationPropertiesBindConstructorProvider.INSTANCE.getBindConstructor(type, false) != null)
? VALUE_OBJECT : JAVA_BEAN;
}
}
BindMethod是个枚举,JAVA_BEAN表示用getter、setter来绑定值,VALUE_OBJECT表示用构造器绑定,判断一个类是JAVA_BEAN还是VALUE_BEAN就看有没有@ConstructorBinding注解
2、@ConfigurationPropertiesScan@ConfigurationPropertiesScan import了ConfigurationPropertiesScanRegistrar,是importBeanDefinitionRegistrar接口的实现。它的逻辑也很简单,就是拿到要扫描的包名,通过ClassPathScanningCandidateComponentProvider这个Scanner去扫描带有ConfigurationProperties的类,然后通过ConfigurationPropertiesBeanRegistrar将扫描到的bean注册到beanFactory
@Override
public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
Set packagesToScan = getPackagesToScan(importingClassmetadata);
scan(registry, packagesToScan);
}
调用链路分析
有@ConstructorBinding注解和没有该注解时,bean的处理逻辑是不同的,没有该注解的话,BindMethod为JAVA_BEAN,ConfigurationPropertiesBindingPostProcessor会进行属性绑定;有该注解的话,BindMethod为VALUE_OBJECT,ConfigurationPropertiesBindingPostProcessor不会处理,但是BeanDefinition有instanceSupplier,这里面会进行属性绑定。两者都会通过ConfigurationPropertiesBinder进行属性绑定,而ConfigurationPropertiesBinder处理BindHandler、Validator等逻辑,最终调用Binder进行绑定
1、JAVA_BEAN的属性绑定ConfigurationPropertiesBindingPostProcessor处理JAVA_BEAN的属性绑定,关键代码如下,逻辑就是为每个需要绑定的bean构造了一个ConfigurationPropertiesBean,然后调用了ConfigurationPropertiesBinder这个binder进行属性绑定,bind方法里会判断是否是VALUE_OBJECT,如果是直接返回不处理
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
bind(ConfigurationPropertiesBean.get(this.applicationContext, bean, beanName));
return bean;
}
private void bind(ConfigurationPropertiesBean bean) {
if (bean == null || hasBoundValueObject(bean.getName())) {
return;
}
Assert.state(bean.getBindMethod() == BindMethod.JAVA_BEAN, "Cannot bind @ConfigurationProperties for bean '"
+ bean.getName() + "'. Ensure that @ConstructorBinding has not been applied to regular bean");
try {
this.binder.bind(bean);
}
catch (Exception ex) {
throw new ConfigurationPropertiesBindException(bean, ex);
}
}
2、VALUE_OBJECT的属性绑定
ConfigurationPropertiesBeanRegistrar在为VALUE_OBJECT创建BeanDefinition时提供了一个instanceSupplier,这个instanceSupplier里面调用ConfigurationPropertiesBinder进行属性绑定
final class ConfigurationPropertiesBeanRegistrar {
private BeanDefinition createBeanDefinition(String beanName, Class> type) {
BindMethod bindMethod = BindMethod.forType(type);
RootBeanDefinition definition = new RootBeanDefinition(type);
definition.setAttribute(BindMethod.class.getName(), bindMethod);
if (bindMethod == BindMethod.VALUE_OBJECT) {
definition.setInstanceSupplier(() -> createvalueObject(beanName, type));
}
return definition;
}
private Object createvalueObject(String beanName, Class> beanType) {
ConfigurationPropertiesBean bean = ConfigurationPropertiesBean.forValueObject(beanType, beanName);
ConfigurationPropertiesBinder binder = ConfigurationPropertiesBinder.get(this.beanFactory);
try {
return binder.bindOrCreate(bean);
}
catch (Exception ex) {
throw new ConfigurationPropertiesBindException(bean, ex);
}
}
}
3、ConfigurationPropertiesBinder
ConfigurationPropertiesBinder对外提供bind和bindOrCreate两个方法,从这里开始涉及到细节和设计上的问题
a、Bindablebindable封装的是能被Binder进行属性绑定的source(可以指一个类(需要先创建一个instance)、也可以指一个instance、还可以是instance里的一个需要被绑定的属性),里面包含这个类、instance的Supplier、注解、绑定限制,属性如下:
public final class Bindable{ private final ResolvableType type; private final ResolvableType boxedType; private final Supplier value; private final Annotation[] annotations; private final EnumSet bindRestrictions; }
type、boxedType就是解析过的类型,value是一个Supplier、可能是null,annotations就是这个类上的注解,bindRestrictions是绑定限制,目前BindRestriction只有一个枚举值NO_DIRECT_PROPERTY,不要直接绑定Spring bean,而对其属性进行绑定
public enum BindRestriction {
NO_DIRECT_PROPERTY
}
这个类提供了一些of方法和with方法来方便的创建bindable对象
of方法
public staticBindable of(Class type) { Assert.notNull(type, "Type must not be null"); return of(ResolvableType.forClass(type)); } public static Bindable ofInstance(T instance) { Assert.notNull(instance, "Instance must not be null"); Class type = (Class ) instance.getClass(); return of(type).withExistingValue(instance); } public static Bindable > listOf(Class
elementType) { return of(ResolvableType.forClassWithGenerics(List.class, elementType)); } public static Bindable of(ResolvableType type) { Assert.notNull(type, "Type must not be null"); ResolvableType boxedType = box(type); return new Bindable<>(type, boxedType, null, NO_ANNOTATIONS, NO_BIND_RESTRICTIONS); }
with方法
public Bindableb、ConfigurationPropertiesBeanwithAnnotations(Annotation... annotations) { return new Bindable<>(this.type, this.boxedType, this.value, (annotations != null) ? annotations : NO_ANNOTATIONS, NO_BIND_RESTRICTIONS); } public Bindable withExistingValue(T existingValue) { Assert.isTrue( existingValue == null || this.type.isArray() || this.boxedType.resolve().isInstance(existingValue), () -> "ExistingValue must be an instance of " + this.type); Supplier value = (existingValue != null) ? () -> existingValue : null; return new Bindable<>(this.type, this.boxedType, value, this.annotations, this.bindRestrictions); } public Bindable withBindRestrictions(BindRestriction... additionalRestrictions) { EnumSet bindRestrictions = EnumSet.copyOf(this.bindRestrictions); bindRestrictions.addAll(Arrays.asList(additionalRestrictions)); return new Bindable<>(this.type, this.boxedType, this.value, this.annotations, bindRestrictions); } public Bindable withSuppliedValue(Supplier suppliedValue) { return new Bindable<>(this.type, this.boxedType, suppliedValue, this.annotations, this.bindRestrictions); }
ConfigurationPropertiesBean封装了一个需要绑定的bean,跟bindable的区别是ConfigurationPropertiesBean跟spring里bean是对应的,而bindable指的是一个能被绑定的source,可以是类、instance、或者一个field,bindable可以脱离spring使用
public final class ConfigurationPropertiesBean {
private final String name;
private final Object instance;
private final ConfigurationProperties annotation;
private final Bindable> bindTarget;
private final BindMethod bindMethod;
}
name就是beanName,instance就是bean实例,bindMethod=VALUE_OBJECT时instance为null
JAVA_BEAN ConfigurationPropertiesBean的创建ConfigurationPropertiesBindingPostProcessor里处理每个bean时调用ConfigurationPropertiesBean#get来创建
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
bind(ConfigurationPropertiesBean.get(this.applicationContext, bean, beanName));
return bean;
}
创建过程如下,调用了Bindable bindTarget = Bindable.of(bindType).withAnnotations(annotations);创建了bindTarget,然后new了一个ConfigurationPropertiesBean
public static ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean, String beanName) {
Method factoryMethod = findFactoryMethod(applicationContext, beanName);
return create(beanName, bean, bean.getClass(), factoryMethod);
}
private static ConfigurationPropertiesBean create(String name, Object instance, Class> type, Method factory) {
ConfigurationProperties annotation = findAnnotation(instance, type, factory, ConfigurationProperties.class);
if (annotation == null) {
return null;
}
Validated validated = findAnnotation(instance, type, factory, Validated.class);
Annotation[] annotations = (validated != null) ? new Annotation[] { annotation, validated }
: new Annotation[] { annotation };
ResolvableType bindType = (factory != null) ? ResolvableType.forMethodReturnType(factory)
: ResolvableType.forClass(type);
Bindable
VALUE_OBJECT ConfigurationPropertiesBean的创建
ConfigurationPropertiesBeanRegistrar创建beanDefinition的instanceSupplier里,创建了ConfigurationPropertiesBean
private Object createvalueObject(String beanName, Class> beanType) {
ConfigurationPropertiesBean bean = ConfigurationPropertiesBean.forValueObject(beanType, beanName);
ConfigurationPropertiesBinder binder = ConfigurationPropertiesBinder.get(this.beanFactory);
try {
return binder.bindOrCreate(bean);
}
catch (Exception ex) {
throw new ConfigurationPropertiesBindException(bean, ex);
}
}
forValueObject里面还是调用了create方式,只是这是instance时null
static ConfigurationPropertiesBean forValueObject(Class> beanClass, String beanName) {
ConfigurationPropertiesBean propertiesBean = create(beanName, null, beanClass, null);
Assert.state(propertiesBean != null && propertiesBean.getBindMethod() == BindMethod.VALUE_OBJECT,
() -> "Bean '" + beanName + "' is not a @ConfigurationProperties value object");
return propertiesBean;
}
c、BindHandler
bindHandler规定了5个回调方法,在对Bindable进行绑定的各个时期会调用回调方法,并采用责任链设计模式,可以自由组合多个handler来实现多种功能,这个接口每个方法都有default实现。这里先分析这种设计模式,何时回调这些方法在分析Binder时一并分析
public interface BindHandler {
BindHandler DEFAULT = new BindHandler() {
};
default Bindable onStart(ConfigurationPropertyName name, Bindable target, BindContext context) {
return target;
}
default Object onSuccess(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result) {
return result;
}
default Object onCreate(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result) {
return result;
}
default Object onFailure(ConfigurationPropertyName name, Bindable> target, BindContext context, Exception error)
throws Exception {
throw error;
}
default void onFinish(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result)
throws Exception {
}
}
AbstractBindHandler持有一个默认的parent,对onCreate之外的4个方法重载了实现,调用了parent的相应方法。那么子类再实现这些方法是,只要调用super.onXXX,就能实现责任链组合不同handler的功能,实际上有些子类实现可以不调用super.onXXX,这样责任链到这里就结束了,所有parent的该方法都不会被调用
public abstract class AbstractBindHandler implements BindHandler {
private final BindHandler parent;
public AbstractBindHandler() {
this(BindHandler.DEFAULT);
}
public AbstractBindHandler(BindHandler parent) {
Assert.notNull(parent, "Parent must not be null");
this.parent = parent;
}
@Override
public Bindable onStart(ConfigurationPropertyName name, Bindable target, BindContext context) {
return this.parent.onStart(name, target, context);
}
@Override
public Object onSuccess(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result) {
return this.parent.onSuccess(name, target, context, result);
}
@Override
public Object onFailure(ConfigurationPropertyName name, Bindable> target, BindContext context, Exception error)
throws Exception {
return this.parent.onFailure(name, target, context, error);
}
@Override
public void onFinish(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result)
throws Exception {
this.parent.onFinish(name, target, context, result);
}
}
看几个具体的实现
IgnoreTopLevelConverterNotFoundBindHandlerIgnoreTopLevelConverterNotFoundBindHandler重载了onFailure,如果当前正在绑定最外层的bean、并且抛出了ConverterNotFoundException,则不抛出这个异常。这也我也看懂到底什么情况下会走到这
public class IgnoreTopLevelConverterNotFoundBindHandler extends AbstractBindHandler {
// construstors
@Override
public Object onFailure(ConfigurationPropertyName name, Bindable> target, BindContext context, Exception error)
throws Exception {
if (context.getDepth() == 0 && error instanceof ConverterNotFoundException) {
return null;
}
throw error;
}
}
ConfigurationPropertiesBindHandler
这个作用是看绑定的Target上有没有@ConfigurationProperties注解,有的话加入绑定限制:NO_DIRECT_PROPERTY,因为不管BindMethod是JAVA_BEAN还是VALUE_OBJECT,都是外部来创建需要绑定的对象的
private static class ConfigurationPropertiesBindHandler extends AbstractBindHandler {
ConfigurationPropertiesBindHandler(BindHandler handler) {
super(handler);
}
@Override
public Bindable onStart(ConfigurationPropertyName name, Bindable target, BindContext context) {
return isConfigurationProperties(target.getType().resolve())
? target.withBindRestrictions(BindRestriction.NO_DIRECT_PROPERTY) : target;
}
private boolean isConfigurationProperties(Class> target) {
return target != null && MergedAnnotations.from(target).isPresent(ConfigurationProperties.class);
}
}
IgnoreErrorsBindHandler
IgnoreErrorsBindHandler是对@ConfigurationProperties#ignoreInvalidFields()=false时的支持,当某个属性转换错误时吞掉异常返回null
public class IgnoreErrorsBindHandler extends AbstractBindHandler {
public IgnoreErrorsBindHandler() {
}
public IgnoreErrorsBindHandler(BindHandler parent) {
super(parent);
}
@Override
public Object onFailure(ConfigurationPropertyName name, Bindable> target, BindContext context, Exception error)
throws Exception {
return (target.getValue() != null) ? target.getValue().get() : null;
}
}
NoUnboundElementsBindHandler
NoUnboundElementsBindHandler是对@ConfigurationProperties#ignoreUnknownFields()=false的支持。忽略细节,其中boundNames记录绑定过的.properties里的属性名,重载了onSuccess方法和onFinish方法,每次绑定成功后将绑定的属性名保存到boundNames,绑定结束后看当前是否在绑定最顶层bean,如果是的话,从context里拿出所有的propertySource,checkNoUnboundElements方法看有没有没绑定的属性,有的话会抛出异常
public class NoUnboundElementsBindHandler extends AbstractBindHandler {
private final Set boundNames = new HashSet<>();
@Override
public Object onSuccess(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result) {
this.boundNames.add(name);
return super.onSuccess(name, target, context, result);
}
@Override
public void onFinish(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result)
throws Exception {
if (context.getDepth() == 0) {
checkNoUnboundElements(name, context);
}
}
}
ValidationBindHandler
ValidationBindHandler支持了绑定时候对属性值的验证,支持jsr303和自定义的验证。属性validators保存了用来对值进行验证的Validator。onFinish的重载中对值进行了验证,遍历了Validator数组对该值进行验证,有不满足限制条件的将会抛出异常
public class ValidationBindHandler extends AbstractBindHandler {
private final Validator[] validators;
public ValidationBindHandler(BindHandler parent, Validator... validators) {
super(parent);
this.validators = validators;
}
@Override
public void onFinish(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result)
throws Exception {
validate(name, target, context, result);
super.onFinish(name, target, context, result);
}
private void validate(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result) {
if (this.exception == null) {
Object validationTarget = getValidationTarget(target, context, result);
Class> validationType = target.getBoxedType().resolve();
if (validationTarget != null) {
validateAndPush(name, validationTarget, validationType);
}
}
if (context.getDepth() == 0 && this.exception != null) {
throw this.exception;
}
}
private Object getValidationTarget(Bindable> target, BindContext context, Object result) {
if (result != null) {
return result;
}
if (context.getDepth() == 0 && target.getValue() != null) {
return target.getValue().get();
}
return null;
}
private void validateAndPush(ConfigurationPropertyName name, Object target, Class> type) {
ValidationResult result = null;
for (Validator validator : this.validators) {
if (validator.supports(type)) {
result = (result != null) ? result : new ValidationResult(name, target);
validator.validate(target, result);
}
}
if (result != null && result.hasErrors()) {
this.exception = new BindValidationException(result.getValidationErrors());
}
}
}
BoundPropertiesTrackingBindHandler
BoundPropertiesTrackingBindHandler用来跟踪绑定成功的属性,重载了onSuccess方法,会调用consumer
public class BoundPropertiesTrackingBindHandler extends AbstractBindHandler {
private final Consumer consumer;
public BoundPropertiesTrackingBindHandler(Consumer consumer) {
Assert.notNull(consumer, "Consumer must not be null");
this.consumer = consumer;
}
@Override
public Object onSuccess(ConfigurationPropertyName name, Bindable> target, BindContext context, Object result) {
if (context.getConfigurationProperty() != null && name.equals(context.getConfigurationProperty().getName())) {
this.consumer.accept(context.getConfigurationProperty());
}
return super.onSuccess(name, target, context, result);
}
}
spring里注册了有一个BoundConfigurationProperties,并且ConfigurationPropertiesBinder#getBindHandler在创建BindHandler时用到了,BoundConfigurationProperties#add方法作为方法引用传给Tracker
private IgnoreTopLevelConverterNotFoundBindHandler getHandler() {
BoundConfigurationProperties bound = BoundConfigurationProperties.get(this.applicationContext);
return (bound != null)
? new IgnoreTopLevelConverterNotFoundBindHandler(new BoundPropertiesTrackingBindHandler(bound::add))
: new IgnoreTopLevelConverterNotFoundBindHandler();
}
BoundConfigurationProperties如下,也就是每次绑定成功的属性都会记录到BoundConfigurationProperties#properties里,可以通过get或getAll查询哪些属性被绑定了
public class BoundConfigurationProperties {
private Map properties = new linkedHashMap<>();
void add(ConfigurationProperty configurationProperty) {
this.properties.put(configurationProperty.getName(), configurationProperty);
}
public ConfigurationProperty get(ConfigurationPropertyName name) {
return this.properties.get(name);
}
public Map getAll() {
return Collections.unmodifiableMap(this.properties);
}
}
BindHandler的组装
ConfigurationPropertiesBinder#getBindHandler为bindTarget创建BindHandler
getHandler创建了IgnoreTopLevelConverterNotFoundBindHandler,BoundPropertiesTrackingBindHandler作为parent,可以记录所有绑定成功的属性如果开启了ignoreInvalidFields,组装上IgnoreErrorsBindHandler如果关闭了ignoreUnknownFields,组装上NoUnboundElementsBindHandler如果有Validator,组装上ValidationBindHandler最后提供了扩展机制,ConfigurationPropertiesBindHandlerAdvisor可以继续组装handler
privated、ConfigurationPropertiesBinder绑定逻辑BindHandler getBindHandler(Bindable target, ConfigurationProperties annotation) { List validators = getValidators(target); BindHandler handler = getHandler(); handler = new ConfigurationPropertiesBindHandler(handler); if (annotation.ignoreInvalidFields()) { handler = new IgnoreErrorsBindHandler(handler); } if (!annotation.ignoreUnknownFields()) { UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter(); handler = new NoUnboundElementsBindHandler(handler, filter); } if (!validators.isEmpty()) { handler = new ValidationBindHandler(handler, validators.toArray(new Validator[0])); } for (ConfigurationPropertiesBindHandlerAdvisor advisor : getBindHandlerAdvisors()) { handler = advisor.apply(handler); } return handler; } private IgnoreTopLevelConverterNotFoundBindHandler getHandler() { BoundConfigurationProperties bound = BoundConfigurationProperties.get(this.applicationContext); return (bound != null) ? new IgnoreTopLevelConverterNotFoundBindHandler(new BoundPropertiesTrackingBindHandler(bound::add)) : new IgnoreTopLevelConverterNotFoundBindHandler(); } }
ConfigurationPropertiesBinder对外提供的bind和bindOrCreate方法本身逻辑很简单,拿到bindTarget和annotation,创建BindHandler,然后创建Binder,将绑定细节交给Binder
BindResult> bind(ConfigurationPropertiesBean propertiesBean) {
Bindable> target = propertiesBean.asBindTarget();
ConfigurationProperties annotation = propertiesBean.getAnnotation();
BindHandler bindHandler = getBindHandler(target, annotation);
return getBinder().bind(annotation.prefix(), target, bindHandler);
}
Object bindOrCreate(ConfigurationPropertiesBean propertiesBean) {
Bindable> target = propertiesBean.asBindTarget();
ConfigurationProperties annotation = propertiesBean.getAnnotation();
BindHandler bindHandler = getBindHandler(target, annotation);
return getBinder().bindOrCreate(annotation.prefix(), target, bindHandler);
}
3、Binder
Binder负责对一个Bindable进行绑定,一个Bindable的属性可能是一个java对象、数组、List、Map等各种情况,Binder会创建代表这些属性的Bindable,递归的去处理这些属性的绑定
a、ConfigurationPropertyName b、ConfigurationProperty c、BindConverter d、AggregateBinder e、Context f、Binder的创建 g、bind核心逻辑to be continued



