栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Boot @ConfigurationProperties(原理)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot @ConfigurationProperties(原理)

上一篇讲用法:https://blog.csdn.net/qq_32868023/article/details/123390627
.properties到Bean的属性绑定是在Bean的实例化阶段由ConfigurationPropertiesBindingPostProcessor处理Bean实现的。首先介绍@EnableConfigurationProperties和@ConfigurationPropertiesScan注解输入注册Bean的,然后介绍ConfigurationPropertiesBindingPostProcessor到Binder的调用链路、属性绑定涉及到的重要的类,最后介绍属性绑定核心类Binder。

Bean的注册 1、@EnableConfigurationProperties

@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, MergedAnnotation annotation) {
		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、Bindable

bindable封装的是能被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 static  Bindable 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 Bindable withAnnotations(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);
	}
b、ConfigurationPropertiesBean

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 bindTarget = Bindable.of(bindType).withAnnotations(annotations);
		if (instance != null) {
			bindTarget = bindTarget.withExistingValue(instance);
		}
		return new ConfigurationPropertiesBean(name, instance, annotation, bindTarget);
	}
 
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);
	}
}

看几个具体的实现

IgnoreTopLevelConverterNotFoundBindHandler

IgnoreTopLevelConverterNotFoundBindHandler重载了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

	private  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();
	}
}
d、ConfigurationPropertiesBinder绑定逻辑

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

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号