// 配置文件属性绑定器
class Binder {
// 标记不是Bean的类
public static final Set<Class<?>> NON_BEAN_CLASSES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(Object.class, Class.class)));
// 配置属性数据源,从这里获取数据进行绑定
public final Iterable<ConfigurationPropertySource> sources;
// 占位符解析器
public final PlaceholdersResolver placeholdersResolver;
// 类型转换器
public final ConversionService conversionService;
// 类型转换器
public final Consumer<PropertyEditorRegistry> propertyEditorInitializer;
// 绑定处理器,在绑定过程中的一些生命周期回调接口
public final BindHandler defaultBindHandler;
// 对象绑定器,将属性绑定到对象上的绑定类
public final List<DataObjectBinder> dataObjectBinders;
public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver, ConversionService conversionService, Consumer<PropertyEditorRegistry> propertyEditorInitializer, BindHandler defaultBindHandler, BindConstructorProvider constructorProvider) {
// 指定要查找的配置属性源
this.sources = sources;
this.placeholdersResolver = (placeholdersResolver != null) ? placeholdersResolver : PlaceholdersResolver.NONE;
this.conversionService = (conversionService != null) ? conversionService : ApplicationConversionService.getSharedInstance();
this.propertyEditorInitializer = propertyEditorInitializer;
// 绑定处理器,在绑定过程中的一些生命周期回调接口
this.defaultBindHandler = (defaultBindHandler != null) ? defaultBindHandler : BindHandler.DEFAULT;
// 构造方法绑定的提供这,因为有的对象只有一个构造方法,并且构造方法的参数可能就是需要绑定的属性
if (constructorProvider == null) {
constructorProvider = BindConstructorProvider.DEFAULT;
}
// 简单的值的对象绑定器
ValueObjectBinder valueObjectBinder = new ValueObjectBinder(constructorProvider);
// JavaBean对象的绑定器
JavaBeanBinder javaBeanBinder = JavaBeanBinder.INSTANCE;
// 保存值对象和JavaBean对象的绑定器
this.dataObjectBinders = Collections.unmodifiableList(Arrays.asList(valueObjectBinder, javaBeanBinder));
}
// 获取可以绑定整个环境对象的所有属性的Binder对象
public void get(Environment environment) {
Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(environment) {
// 从ConfigurableEnvironment环境对象中获取到所有的属性资源
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
// 获取附加的配置属性源configurationProperties,上面已经附加过了
ConfigurationPropertySourcesPropertySource attached = (ConfigurationPropertySourcesPropertySource) sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
// 如果没有附加上,
if (attached == null) {
// 返回SpringConfigurationPropertySources
return from(sources) {
return new SpringConfigurationPropertySources(sources);
}
}
// 返回附加配置的源数据
return attached.getSource();
}
// 创建属性占位符解析器
PropertySourcesPlaceholdersResolver placeholdersResolver = new PropertySourcesPlaceholdersResolver(environment);
// 返回对象属性绑定器
// 创建属性绑定对象,该类专门用于绑定ConfigurationPropertySources中的属性
return new Binder(sources, placeholdersResolver, null, null, defaultBindHandler);
}
/**
* 获取当前对象保存的ConfigurationPropertySource: sources属性中的name对应的值,然后绑定到target对象,然后返回BindResult对象
*
* @param name 通过给定的字符串Key,使用"."进行分割,得到分割后的属性元素名称
* @param target 将给定的目标对象类型,包装为Bindable类型,内部会对简单类型进行包装成数组的第一个元素,保存了目标类的原始类型和包装类型
* @param handler 绑定处理器,在绑定过程中的一些生命周期回调接口
* @return 绑定后的结果, 存储了绑定的值的最终结果
*/
public <T> BindResult<T> bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler) {
T bound = bind(name, target, handler, false);
// 将绑定的最终结果封装为BindResul对象
return BindResult.of(bound);
}
/**
* 获取当前对象保存的ConfigurationPropertySource: sources属性中的name对应的值,然后绑定到target对象,然后返回BindResult对象
*
* @param name 通过给定的字符串Key,使用"."进行分割,得到分割后的属性元素名称
* @param target 将给定的目标对象类型,包装为Bindable类型,内部会对简单类型进行包装成数组的第一个元素,保存了目标类的原始类型和包装类型
* @param handler 绑定处理器,在绑定过程中的一些生命周期回调接口
* @return 绑定后的最终结果
*/
public <T> T bindOrCreate(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler) {
return bind(name, target, handler, true);
}
/**
* 绑定并创建,如果绑定的属性不存在,则创建默认值
*
* @param name 通过给定的字符串Key,使用"."进行分割,得到分割后的属性元素名称
* @param target 将给定的目标对象类型,包装为Bindable类型,内部会对简单类型进行包装成数组的第一个元素,保存了目标类的原始类型和包装类型
* @param handler 绑定处理器,在绑定过程中的一些生命周期回调接口
* @return 绑定后的最终结果
*/
public <T> T bindOrCreate(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler) {
return bind(name, target, handler, true);
}
/**
* 获取当前对象保存的ConfigurationPropertySource: sources属性中的name对应的值,然后绑定到target对象,然后返回BindResult对象
*
* @param name 通过给定的字符串Key,使用"."进行分割,得到分割后的属性元素名称
* @param target 将给定的目标对象类型,包装为Bindable类型,内部会对简单类型进行包装成数组的第一个元素,保存了目标类的原始类型和包装类型
* @param handler 绑定处理器,在绑定过程中的一些生命周期回调接口
* @param create 如果绑定的值为空,是否需要创建默认值
* @return 绑定后的最终结果
*/
public <T> T bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, boolean create) {
// 如果没有指定BindHandler,则使用默认的BindHandler, BindHandler.DEFAULT
handler = (handler != null) ? handler : this.defaultBindHandler;
// 创建绑定的上下文对象
Context context = new Context();
// 绑定属性,该方法不支持递归绑定属性
return bind(name, target, handler, context, false, create);
}
/**
* @param name 通过给定的字符串Key,使用"."进行分割,得到分割后的属性元素名称
* @param target 将给定的目标对象类型,包装为Bindable类型,内部会对简单类型进行包装成数组的第一个元素,保存了目标类的原始类型和包装类型
* @param handler 绑定处理器,在绑定过程中的一些生命周期回调接口
* @param context 绑定过程中的上下文对象
* @param allowRecursiveBinding 是否允许递归绑定属性
* @param create 如果绑定的值为空,是否需要创建默认值
* @return 绑定后的最终结果
*/
public <T> T bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Context context, boolean allowRecursiveBinding, boolean create) {
// 重置上下文绑定的配置属性
context.clearConfigurationProperty();
try {
// 执行BindHandler的onStart生命周期方法
Bindable<T> replacementTarget = handler.onStart(name, target, context);
// 如果onStart回调将目标对象返回为空了,则直接处理空的结果逻辑
// 因为默认返回的就是target
if (replacementTarget == null) {
return handleBindResult(name, target, handler, context, null, create);
}
// 将onStart回调最终的结果替换原来的目标对象类型
target = replacementTarget;
// 绑定对象,返回绑定后的值
Object bound = bindObject(name, target, handler, context, allowRecursiveBinding);
// 处理绑定结果
return handleBindResult(name, target, handler, context, bound, create);
} catch (Exception ex) {
// 处理绑定异常结果
return handleBindError(name, target, handler, context, ex);
}
}
// 处理绑定的结果,转换为最终的结果对象
public <T> T handleBindResult(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Context context, Object result, boolean create) throws Exception {
// 如果绑定的结果不为null
if (result != null) {
// 执行BindHandler对象的onSuccess生命周期回调
result = handler.onSuccess(name, target, context, result);
// 对绑定结果进行类型转换,将结果对象转换为目标对象类型,得到最终结果
result = context.getConverter().convert(result, target);
}
// 绑定的结果为null,并且需要给目标类型创建默认值
if (result == null && create) {
// 创建目标类型的实例对象
result = create(target, context);
// 执行BindHandler对象的onCreate生命周期回调
result = handler.onCreate(name, target, context, result);
// 对结果进行类型转换
result = context.getConverter().convert(result, target);
}
// 执行BindHandler对象的onFinish生命周期回调
// 其中,在ValidationBindHandler中,onFinish会给result结果对象进行参数校验
handler.onFinish(name, target, context, result);
// 其他情况,也就是结果为空,并且没有指定要创建默认的实例对象,直接进行类型转换
return context.getConverter().convert(result, target);
}
// 创建目标类型的默认对象
public Object create(Bindable<?> target, Context context) {
// 遍历对象绑定器,调用他们的创建方法,根据目标对象不同使用不同的创建实例的绑定器,默认存在两个
// 前面已经对简单类型做了过滤,只要是简单类型或者java开头的类,或者是Class,Object不绑定
// 下面的只处理剩下的条件
// 1: ValueObjectBinder
// 1.1. 该类不处理枚举,抽象类型
// 1.2. 之后再通过BindConstructorProvider类是否可以提供可用的构造方法
// BindConstructorProvider是一个抽象类,有不同的实现,但是作用都一样
// 就是只会处理构造方法只有一个,并且存在构造参数的情况,才会进行处理
// 2: JavaBeanBinder: ValueObjectBinder不处理的,由JavaBeanBinder创建
// 该类简单粗暴,直接使用默认的构造方法实例化
// 如果没有默认的,又不能被ValueObjectBinder处理,则会抛出异常
for (DataObjectBinder dataObjectBinder : this.dataObjectBinders) {
// 在ValueObjectBinder对象中,
// 在JavaBeanBinder对象中,直接返回实例化
/**
* {@link ValueObjectBinder#create,JavaBeanBinder#create}
*/
Object instance = dataObjectBinder.create(target, context);
// 返回创建的实例
if (instance != null) {
return instance;
}
}
return null;
}
// 属性绑定
public <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Context context, boolean allowRecursiveBinding) {
// 遍历存储的上下文中的配置属性对象,默认为传递的Binder对象的所有配置属性集合
// 如果是聚合属性,则进行了优化,返回的是缓存在上下文中的配置属性
// 这是在聚合属性绑定的时候使用到,因为聚合属性绑定的对象,绑定的值都在同一个ConfigurationPropertySource中
// 就不需要每次去遍历所有的ConfigurationPropertySource去找,这样费性能
ConfigurationProperty property = findProperty(name, context);
// 如果不存在该属性,或者该key不存在后代属性,并且解析的深度不为0(递归绑定的情况)
if (property == null && containsNoDescendantOf(context.getSources(), name) && context.depth != 0) {
return null;
}
// 获取聚合属性绑定器,绑定数组,集合,Map的绑定类
// 如果不是聚合类型,返回null
AggregateBinder<?> aggregateBinder = getAggregateBinder(target, context);
// 聚合属性绑定器
if (aggregateBinder != null) {
// 绑定聚合属性
return bindAggregate(name, target, handler, context, aggregateBinder);
}
// 如果使用该key找到了属性
if (property != null) {
try {
// 绑定属性,返回需要绑定的属性的最终转换后的值,但是还没有绑定
return bindProperty(target, context, property);
} catch (ConverterNotFoundException ex) {
// 如果属性绑定出现异常,出现异常都是因为类型转换失败,所以再尝试一下对将整个对象重新进行绑定
Object instance = bindDataObject(name, target, handler, context, allowRecursiveBinding);
// 对象绑定成功,返回绑定成功的对象
if (instance != null) {
return instance;
}
// 否则抛出异常
throw ex;
}
}
// 数据对象绑定,将整个对象进行递归绑定
return bindDataObject(name, target, handler, context, allowRecursiveBinding);
}
// 获取聚合属性绑定器
public AggregateBinder<?> getAggregateBinder(Bindable<?> target, Context context) {
// 需要绑定的类型
Class<?> resolvedType = target.getType().resolve(Object.class);
// 如果绑定的类型是Map
if (Map.class.isAssignableFrom(resolvedType)) {
// 返回Map对应的绑定器
return new MapBinder(context);
}
// 如果是集合,返回集合对应的绑定器
if (Collection.class.isAssignableFrom(resolvedType)) {
return new CollectionBinder(context);
}
// 如果是数组,返回对应的数组绑定器
if (target.getType().isArray()) {
return new ArrayBinder(context);
}
// 不是聚合属性,返回null
return null;
}
// 绑定聚合属性
public <T> Object bindAggregate(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Context context, AggregateBinder<?> aggregateBinder) {
// 创建一个回调,用于聚合属性绑定
AggregateElementBinder elementBinder = (ConfigurationPropertyName itemName, Bindable<?> itemTarget, ConfigurationPropertySource source) -> {
// 是否支持递归绑定,aggregateBinder是一个抽象类,其中有Array,Collection,Map的绑定器,而Array,Collection又继承IndexAggregateBinder
// 当为Map的时候,允许递归绑定
// 当为IndexAggregateBinder的时候,则需要判断该属性数据源是不是可迭代的IterableConfigurationPropertySource类型
boolean allowRecursiveBinding = aggregateBinder.isAllowRecursiveBinding(source);
// 给定一个需要返回绑定结果对象的回调,可以获取到绑定成功之后的对象
// 该回调就是对聚合属性进行对象绑定
Supplier<?> supplier = () -> bind(itemName, itemTarget, handler, context, allowRecursiveBinding, false);
// 记录正在绑定的属性配置源并进行绑定
return context.withSource(source, supplier);
};
// 记录深度并绑定聚合属性
return context.withIncreasedDepth(() -> aggregateBinder.bind(name, target, elementBinder));
}
/**
* 查找属性是否存在
*
* @param name 属性名称
* @param context 绑定上下文
* @return 找到的属性的ConfigurationProperty对象
*/
public ConfigurationProperty findProperty(ConfigurationPropertyName name, Context context) {
// 如果不存在名称,不存在任何key
if (name.isEmpty()) {
return null;
}
// 遍历存储的上下文中的配置属性对象,默认为传递的Binder对象的所有配置属性集合
// 如果是聚合属性,则进行了优化,返回的是缓存在上下文中的配置属性
// 这是在聚合属性绑定的时候使用到,因为聚合属性绑定的对象,绑定的值都在同一个ConfigurationPropertySource中
// 就不需要每次去遍历所有的ConfigurationPropertySource去找,这样费性能
for (ConfigurationPropertySource source : context.getSources()) {
// 查找属性配置中是否存在该key的配置
ConfigurationProperty property = source.getConfigurationProperty(name);
// 如果存在,表示存在该属性值
if (property != null) {
return property;
}
}
return null;
}
/**
* 处理绑定异常
*/
public <T> T handleBindError(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Context context, Exception error) {
try {
// 执行BindHandler的onFailure回调
Object result = handler.onFailure(name, target, context, error);
// 对异常结果进行类型转换
return context.getConverter().convert(result, target);
} catch (Exception ex) {
// 如果异常回调没有处理或者再出问题,则抛出异常
throw new BindException(name, target, context.getConfigurationProperty(), ex);
}
}
/**
* 绑定属性,返回需要绑定的属性的最终转换后的值,但是还没有绑定
*/
public <T> Object bindProperty(Bindable<T> target, Context context, ConfigurationProperty property) {
// 将找到的对应key的属性值保存到上下文中
context.setConfigurationProperty(property);
// 获取属性的值
Object result = property.getValue();
// 解析占位符表达式
result = this.placeholdersResolver.resolvePlaceholders(result);
// 对属性值进行类型转换
result = context.getConverter().convert(result, target);
// 返回最终需要绑定的结果
return result;
}
// 数据对象绑定,将整个对象进行递归绑定
public Object bindDataObject(ConfigurationPropertyName name, Bindable<?> target, BindHandler handler, Context context, boolean allowRecursiveBinding) {
// 如果是不能绑定的Bean对象,就不绑定
// java内部的类,简单类型,Class类型,Object类型不能绑定
if (isUnbindableBean(name, target, context)) {
return null;
}
// 获取目标类型
Class<?> type = target.getType().resolve(Object.class);
// 如果不支持递归绑定,直接返回,如果当前整个上下文已经在绑定属性,则isBindingDataObject返回true
if (!allowRecursiveBinding && context.isBindingDataObject(type)) {
return null;
}
// 创建一个数据对象属性的绑定器,用于递归绑定属性中的属性
// 因为当前绑定的对象是一个内部还有属性的对象,所以还需要绑定当前对象内部的属性
// 绑定操作就是一个递归操作,属性对象内可能还有属性
DataObjectPropertyBinder propertyBinder = (propertyName, propertyTarget) -> bind(name.append(propertyName), propertyTarget, handler, context, false, false);
// 给定一个需要返回绑定结果对象的回调,可以获取到绑定成功之后的对象
Supplier supplier = () -> {
// 遍历所有的数据对象绑定器
for (DataObjectBinder dataObjectBinder : this.dataObjectBinders) {
/**
* {@link JavaBeanBinder,ValueObjectBinder}
*/
Object instance = dataObjectBinder.bind(name, target, context, propertyBinder);
// 返回绑定好的实例对象
if (instance != null) {
return instance;
}
}
return null;
}
// 开始执行数据绑定
return context.withDataObject(type, supplier);
}
// Map类型属性的绑定
class MapBinder extends AggregateBinder<Map<Object, Object>> {
// 最终绑定的结果
public static final Bindable<Map<String, String>> STRING_STRING_MAP = Bindable.mapOf(String.class, String.class);
protected Object bindAggregate(ConfigurationPropertyName name, Bindable<?> target, AggregateElementBinder elementBinder) {
// 根据绑定的目标类型创建对应的Map对象
Map<Object, Object> map = CollectionFactory.createMap((target.getValue() != null) ? Map.class : target.getType().resolve(Object.class), 0);
//处理目标类型,如果是Properties,返回STRING_STRING_MAP对象,其他的不处理
Bindable<?> resolvedTarget = resolveTarget(target);
// 是否存在子属性
boolean hasDescendants = hasDescendants(name);
// 遍历存储的上下文中的配置属性对象,默认为传递的Binder对象的所有配置属性集合
// 如果是聚合属性,则进行了优化,返回的是缓存在上下文中的配置属性
// 这是在聚合属性绑定的时候使用到,因为聚合属性绑定的对象,绑定的值都在同一个ConfigurationPropertySource中
// 就不需要每次去遍历所有的ConfigurationPropertySource去找,这样费性能
for (ConfigurationPropertySource source : getContext().getSources()) {
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
// 查找属性配置中是否存在该key的配置
ConfigurationProperty property = source.getConfigurationProperty(name);
// 如果存在属性,并且不存在子属性,直接使用该值进行类型转换并返回
if (property != null && !hasDescendants) {
return getContext().getConverter().convert(property.getValue(), target);
}
// 将属性配置源对象转换为可进行过滤的属性配置源对象
// 这样,再原来基础上的配置数据源同时有过滤的功能
source = source.filter(name::isAncestorOf);
}
// 创建Map元素绑定器
EntryBinder binder = new EntryBinder(name, resolvedTarget, elementBinder);
// 绑定键值对到创建的map元素中
binder.bindEntries(source, map);
}
// 如果没有绑定到元素,返回空,绑定到了,返回绑定完成的map
return map.isEmpty() ? null : map;
}
// 处理目标类型
public Bindable<?> resolveTarget(Bindable<?> target) {
// 如果是Properties,返回STRING_STRING_MAP对象,其他的不处理
Class<?> type = target.getType().resolve(Object.class);
if (Properties.class.isAssignableFrom(type)) {
return STRING_STRING_MAP;
}
return target;
}
// 是否可以循环绑定
protected boolean isAllowRecursiveBinding(ConfigurationPropertySource source) {
return true;
}
}
// Map中键值对的绑定器
private class EntryBinder {
// 配置的根Key
private final ConfigurationPropertyName root;
// 元素绑定器,就是递归绑定
private final AggregateElementBinder elementBinder;
// Map类型
private final ResolvableType mapType;
// Map的Key的类型
private final ResolvableType keyType;
// Map的Value类型
private final ResolvableType valueType;
EntryBinder(ConfigurationPropertyName root, Bindable<?> target, AggregateElementBinder elementBinder) {
this.root = root;
this.elementBinder = elementBinder;
this.mapType = target.getType().asMap();
this.keyType = this.mapType.getGeneric(0);
this.valueType = this.mapType.getGeneric(1);
}
// 绑定键值对
public void bindEntries(ConfigurationPropertySource source, Map<Object, Object> map) {
if (source instanceof IterableConfigurationPropertySource) {
// 遍历所有属性
for (ConfigurationPropertyName name : (IterableConfigurationPropertySource) source) {
// 获取绑定值的类型
Bindable<?> valueBindable = getValueBindable(name);
// 获取需要绑定到Map元素的Key
// 通过下面算法,找到需要保存的map中的key,要一层一层剥开这些key,来存储
ConfigurationPropertyName entryName = getEntryName(source, name);
// 获取到该名称去除根key的属性名name
// 说白了就是map的key要一层一层拨开存入,luck.id => {"luck":{"id":1}}
String keyName = getKeyName(entryName);
// 使用类型转换器,将key的类型转换为Map中key的类型
Object key = getContext().getConverter().convert(keyName, this.keyType);
// 递归执行元素绑绑定,然后将绑定结果保存到给定的结果map中
/**
* {@link Binder#bindAggregate}
*/
map.computeIfAbsent(key, (k) -> this.elementBinder.bind(entryName, valueBindable));
}
}
}
// 获取需要绑定到Map元素的Key
// 通过下面算法,找到需要保存的map中的key,要一层一层剥开这些key,来存储
private ConfigurationPropertyName getEntryName(ConfigurationPropertySource source, ConfigurationPropertyName name) {
// 获取值的类型
Class<?> resolved = this.valueType.resolve(Object.class);
// 如果是集合或者数组
if (Collection.class.isAssignableFrom(resolved) || this.valueType.isArray()) {
// 切割key,因为当前key不是在上一层的key中,那么就要回到上一层的key在进行操作
// 内部就是调用name.chop,区别只是遍历,找一个就可以
return chopNameAtNumericIndex(name);
}
// 如果当前根Key不是给定属性名称的上一层key
// 再判断该值是否允许嵌套映射,如果允许嵌套映射,或者该类是一个非标量类
// isScalarValue: 只有Map中值的类型是java.lang包下或者是枚举,并且配置属性中的值还可以进行类型转换为目标值对象,才是标量
if (!this.root.isParentOf(name) && (isValueTreatedAsNestedMap() || !isScalarValue(source, name))) {
// 切割key,因为当前key不是在上一层的key中,那么就要回到上一层的key在进行操作
return name.chop(this.root.getNumberOfElements() + 1);
}
// 返回给定的key名称
return name;
}
// 获取到该名称去除根key的name
// root: 根key只有一层 例如: luck
// name: 当前key的名称的层数 luck.id
// 在name的完整key中,luck.id元素保存方式
// [0,6] 所有用"."拼接的key的起始位集合,分别为第一组key的起始位置和第一组key的结束位置
// [4,8] 例如:luck => (0-4) id => (6,8)
// 因此,name.getElement(i, Form.ORIGINAL)就是获取第几组元素的位置,然后就知道名称
// 结果为: id
private String getKeyName(ConfigurationPropertyName name) {
StringBuilder result = new StringBuilder();
// root: 根key只有一层 例如: luck
// name: 当前key的名称的层数 luck.id
for (
int i = this.root.getNumberOfElements(); i < name.getNumberOfElements(); i++) {
// 如果有多层,使用.分割
if (result.length() != 0) {
result.append('.');
}
// 获取到该名称去除根key的name
// root: 根key只有一层 例如: luck
// name: 当前key的名称的层数 luck.id
// 在name的完整key中,luck.id元素保存方式
// [0,6] 所有用"."拼接的key的起始位集合,分别为第一组key的起始位置和第一组key的结束位置
// [4,8] 例如:luck => (0-4) id => (6,8)
// 因此,name.getElement(i, Form.ORIGINAL)就是获取第几组元素的位置,然后就知道名称
// 结果为: id
result.append(name.getElement(i, Form.ORIGINAL));
}
return result.toString();
}
// 获取绑定值的类型
private Bindable<?> getValueBindable(ConfigurationPropertyName name) {
// 如果当前根Key不是给定属性名称的上一层key,并且该值是否允许嵌套映射,则当前绑定的值又是一个Map类型
if (!this.root.isParentOf(name) && isValueTreatedAsNestedMap()) {
return Bindable.of(this.mapType);
}
// 否则返回值的类型
return Bindable.of(this.valueType);
}
/**
* 是否是标量值,只有Map中值的类型是java.lang包下或者是枚举,并且配置属性中的值还可以进行类型转换为目标值对象,才是标量
*/
private boolean isScalarValue(ConfigurationPropertySource source, ConfigurationPropertyName name) {
// 获取值的类型
Class<?> resolved = this.valueType.resolve(Object.class);
// 如果值不是java.lang,而且还不是枚举,表示该类型不是标量类型
if (!resolved.getName().startsWith("java.lang") && !resolved.isEnum()) {
return false;
}
// 如果是java.lang包下的类,或者是枚举,从配置属性中获取对应key的值
ConfigurationProperty property = source.getConfigurationProperty(name);
// 如果不存在,表示不是标量值
if (property == null) {
return false;
}
// 如果存在配置值
Object value = property.getValue();
// 先进行占位符解析
value = getContext().getPlaceholdersResolver().resolvePlaceholders(value);
// 使用类型转换器可以将解析的值转换为Map中value的值类型,表示该值是一个标量值
return getContext().getConverter().canConvert(value, this.valueType);
}
}
// 可以索引绑定的类型属性的绑定
class IndexedElementsBinder<T> extends AggregateBinder<T> {
// 开始进行下标绑定
protected final void bindIndexed(ConfigurationPropertyName name, Bindable<?> target, AggregateElementBinder elementBinder, ResolvableType aggregateType, ResolvableType elementType, IndexedCollectionSupplier result) {
// 遍历存储的上下文中的配置属性对象,默认为传递的Binder对象的所有配置属性集合
// 如果是聚合属性,则进行了优化,返回的是缓存在上下文中的配置属性
// 这是在聚合属性绑定的时候使用到,因为聚合属性绑定的对象,绑定的值都在同一个ConfigurationPropertySource中
// 就不需要每次去遍历所有的ConfigurationPropertySource去找,这样费性能
for (ConfigurationPropertySource source : getContext().getSources()) {
// 使用下标进行绑定
bindIndexed(source, name, target, elementBinder, result, aggregateType, elementType);
// 如果绑定成功,直接结束
if (result.wasSupplied() && result.get() != null) {
return;
}
}
}
// 查找属性值是否存在,如果存在,直接绑定值,不存在则需要根据下标绑定
public void bindIndexed(ConfigurationPropertySource source, ConfigurationPropertyName root, Bindable<?> target, AggregateElementBinder elementBinder, IndexedCollectionSupplier collection, ResolvableType aggregateType, ResolvableType elementType) {
// 查找属性配置中是否存在该key的配置
ConfigurationProperty property = source.getConfigurationProperty(root);
// 如果存在key对应的值
if (property != null) {
// 如果存在属性值,直接进行值绑定
// 这种情况就是string类型的数据,例如 dev,test,使用key确实可以获取到值,但是实际要接收的是数组
// 所以需要进行转换并绑定
bindValue(target, collection.get(), aggregateType, elementType, property.getValue());
} else {
// 获取配置属性的值,进行下标绑定
bindIndexed(source, root, elementBinder, collection, elementType);
}
}
// 如果存在属性值,直接进行值绑定
// 这种情况就是string类型的数据,例如 dev,test,使用key确实可以获取到值,但是实际要接收的是数组
// 所以需要进行转换并绑定
public void bindValue(Bindable<?> target, Collection<Object> collection, ResolvableType aggregateType, ResolvableType elementType, Object value) {
// 如果值为String类型吧况且是空的,不绑定
if (value instanceof String && !StringUtils.hasText((String) value)) {
return;
}
// 对stinrg的元素值进行类型转换,转换为给定的聚合类型
// 使用","等等分割,转让为聚合类型
Object aggregate = convert(value, aggregateType, target.getAnnotations());
// 获取带泛型集合的解析类型
ResolvableType collectionType = ResolvableType.forClassWithGenerics(collection.getClass(), elementType);
// 再将元素转换为带有泛型的集合类型
Collection<Object> elements = convert(aggregate, collectionType);
// 将转换后的集合元素保存
collection.addAll(elements);
}
// 正式开启下标绑定
public void bindIndexed(ConfigurationPropertySource source, ConfigurationPropertyName root, AggregateElementBinder elementBinder, IndexedCollectionSupplier collection, ResolvableType elementType) {
// 从属性配置文件中,获取这个key对应的多个值
MultiValueMap<String, ConfigurationProperty> knownIndexedChildren = getKnownIndexedChildren(source, root);
// 遍历配置文件key对应的所有的值
for (int i = 0; i < Integer.MAX_VALUE; i++) {
// 拼接属性名 luck.names[0] luck.names[i]
ConfigurationPropertyName name = root.append((i != 0) ? "[" + i + "]" : INDEX_ZERO);
/**
* 使用元素绑定器进行属性绑定,获取绑定的属性值
* {@link Binder#bindAggregate}
*/
Object value = elementBinder.bind(name, Bindable.of(elementType), source);
// 如果绑定失败
if (value == null) {
break;
}
// 绑定成功,删除元素
knownIndexedChildren.remove(name.getLastElement(Form.UNIFORM));
// 将需要绑定的属性添加到集合中
collection.get().add(value);
}
// 如果上面有元素失败,则抛出子元素绑定异常
assertNoUnboundChildren(knownIndexedChildren);
}
// 是否可以循环绑定
protected boolean isAllowRecursiveBinding(ConfigurationPropertySource source) {
return source == null || source instanceof IterableConfigurationPropertySource;
}
}
// 集合类型绑定
class CollectionBinder extends IndexedElementsBinder<Collection<Object>> {
protected Object bindAggregate(ConfigurationPropertyName name, Bindable<?> target, AggregateElementBinder elementBinder) {
// 获取到绑定的集合类型
Class<?> collectionType = (target.getValue() != null) ? List.class : target.getType().resolve(Object.class);
// 获取带有泛型的目标聚合类型
ResolvableType aggregateType = ResolvableType.forClassWithGenerics(List.class, target.getType().asCollection().getGenerics());
// 获取到集合中的元素类型
ResolvableType elementType = target.getType().asCollection().getGeneric();
// 创建一个返回Collection的Supplier对象
IndexedCollectionSupplier result = new IndexedCollectionSupplier(() -> CollectionFactory.createCollection(collectionType, elementType.resolve(), 0));
// 进行属性下标绑定
bindIndexed(name, target, elementBinder, aggregateType, elementType, result);
// 如果存在Supplier对象,上面传递了ArrayList::new,创建ArrayList对象
// 并且执行了bindIndexed进行元素绑定了
// 获取绑定后的元素集合,因为数组是不可变的,所以只能先用集合代替,最终转换为数组
if (result.wasSupplied()) {
// 返回绑定结果
return result.get();
}
return null;
}
}
// 数组类型绑定
class ArrayBinder extends IndexedElementsBinder<Object> {
// 绑定聚合属性
protected Object bindAggregate(ConfigurationPropertyName name, Bindable<?> target, AggregateElementBinder elementBinder) {
// 创建一个返回ArrayList的Supplier对象
IndexedCollectionSupplier result = new IndexedCollectionSupplier(ArrayList::new);
// 获取聚合类型
ResolvableType aggregateType = target.getType();
// 获取聚合类型中的元素类型
ResolvableType elementType = target.getType().getComponentType();
// 进行属性下标绑定
bindIndexed(name, target, elementBinder, aggregateType, elementType, result);
// 如果存在Supplier对象,上面传递了ArrayList::new,创建ArrayList对象
// 并且执行了bindIndexed进行元素绑定了
// 获取绑定后的元素集合,因为数组是不可变的,所以只能先用集合代替,最终转换为数组
if (result.wasSupplied()) {
// 获取绑定后的元素集合,因为数组是不可变的,所以只能先用集合代替,最终转换为数组
List<Object> list = (List<Object>) result.get();
// 根据元素类型和绑定的大小创建数组
Object array = Array.newInstance(elementType.resolve(), list.size());
// 将绑定到集合中的元素放到数组中
for (int i = 0; i < list.size(); i++) {
Array.set(array, i, list.get(i));
}
// 返回数组对象
return array;
}
return null;
}
}
// 配置属性的源信息
public static class ConfigurationPropertySource {
// 从配置属性中获取指定名称的属性值对象
// 获取配置属性对象,下面源码是核心的源码
public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
// 获取属性名称
String propertySourceName = mapping.getPropertySourceName();
// 从属性配置中获取对应属性名称对应的值
Object value = getPropertySource().getProperty(propertySourceName);
// 如果没有找到属性值,则继续找下一个配置属性来查找
if (value == null) {
continue;
}
// 获取ConfigurationPropertyName对象
ConfigurationPropertyName configurationPropertyName = mapping.getConfigurationPropertyName();
// 将当前找到的属性源对象和属性名对象保存到Origin中
// 就是记录当前属性的值是出自哪里
Origin origin = PropertySourceOrigin.get(this.propertySource, propertySourceName);
// 返回ConfigurationProperty对象
return ConfigurationProperty.of(configurationPropertyName, value, origin);
}
}
// 绑定的上下文
public static class Context {
// 当前对象绑定的深度
public int depth;
// 当前对象从哪个ConfigurationPropertySource中获取属性进行绑定
public final List<ConfigurationPropertySource> source = Arrays.asList((ConfigurationPropertySource) null);
public int sourcePushCount;
// 正在进行数据绑定的对象类型
public final Deque<Class<?>> dataObjectBindings = new ArrayDeque<>();
// 正在进行构造绑定的类型
public final Deque<Class<?>> constructorBindings = new ArrayDeque<>();
// 当前正在绑定的属性配置信息,内部包含当前绑定的key,绑定的值,该属性的来源信息
public ConfigurationProperty configurationProperty;
/**
* 开始执行数据绑定
*
* @param type 正在绑定的类型
* @param supplier 提供获取绑定成功之后结果的回调,在内部实现绑定,并且返回绑定结果
* @return
*/
public <T> T withDataObject(Class<?> type, Supplier<T> supplier) {
// 记录正在绑定的对象类型
this.dataObjectBindings.push(type);
// 记录递归绑定的深度+1
increaseDepth();
// 记录深度并绑定
T res = withIncreasedDepth(supplier);
// 绑定完成,深度-1
decreaseDepth();
// 删除正在绑定的对象类型
this.dataObjectBindings.pop();
// 返回绑定的结果
return res;
}
/**
* 是否是正在绑定的对象类型
*/
public boolean isBindingDataObject(Class<?> type) {
return this.dataObjectBindings.contains(type);
}
// 保存正在进行构造绑定的类型
public void pushConstructorBoundTypes(Class<?> value) {
this.constructorBindings.push(value);
}
// 青储正在构造绑定的类型
public void popConstructorBoundTypes() {
this.constructorBindings.pop();
}
// 是否存在嵌套绑定
public boolean isNestedConstructorBinding() {
return !this.constructorBindings.isEmpty();
}
// 清空正在绑定的属性信息
public void clearConfigurationProperty() {
this.configurationProperty = null;
}
// 获取当前正在绑定的对象从哪个ConfigurationPropertySource中获取属性绑定
public Iterable<ConfigurationPropertySource> getSources() {
// 如果是聚合属性的绑定操作,获取保存在上下文中的配置属性对象
if (this.sourcePushCount > 0) {
// 这是在聚合属性绑定的时候使用到,因为聚合属性绑定的对象,绑定的值都在同一个ConfigurationPropertySource中
// 就不需要每次去遍历所有的ConfigurationPropertySource去找,这样费性能
return this.source;
}
// 否则返会保存在Binder对象中的属性对象
return Binder.this.sources;
}
// 记录正在绑定的属性配置源并进行绑定
public <T> T withSource(ConfigurationPropertySource source, Supplier<T> supplier) {
// 如何没有提供配置数据源
if (source == null) {
// 直接回调属性的绑定操作,返回绑定成功的结果
// Supplier<?> supplier = () -> bind(itemName, itemTarget, handler, context, allowRecursiveBinding, false);
return supplier.get();
}
// 保存当前正在绑定的配置属性对象,这是一个优化操作
// 这是在聚合属性绑定的时候使用到,因为聚合属性绑定的对象,绑定的值都在同一个ConfigurationPropertySource中
// 就不需要每次去遍历所有的ConfigurationPropertySource去找,这样费性能
this.source.set(0, source);
/**
* {@link Context#getSources}
*/
// 记录集合属性绑定的深度+1
this.sourcePushCount++;
// 回调属性的绑定操作,返回绑定成功的结果
// Supplier<?> supplier = () -> bind(itemName, itemTarget, handler, context, allowRecursiveBinding, false);
T res = supplier.get();
// 绑定成功,减少聚合属性绑定的深度-1
this.sourcePushCount--;
// 返回绑定结果
return res;
}
// 记录深度并绑定
public <T> T withIncreasedDepth(Supplier<T> supplier) {
// 增加深度+1
this.depth++;
// 回调绑定操作,这个回调是处理对象,或者聚合属性的绑定操作
T res = supplier.get();
// 绑定成功,深度-1
this.depth--;
// 返回绑定结果
return res;
}
}
// 属性配置的值ConfigurationProperty
public class ConfigurationProperty {
// 属性名
public final ConfigurationPropertyName name;
// 属性值
public final Object value;
// 属性的原始对象
public final Origin origin;
class Origin {
// 属性对应的配置属性集合
public final PropertySource<?> propertySource;
// 属性名称
public final String propertyName;
}
}
// 1: ValueObjectBinder
// 1.1. 该类不处理枚举,抽象类型
// 1.2. 之后再通过BindConstructorProvider类是否可以提供可用的构造方法
// BindConstructorProvider是一个抽象类,有不同的实现,但是作用都一样
// 就是只会处理构造方法只有一个,并且存在构造参数的情况,才会进行处理
// 2: JavaBeanBinder: ValueObjectBinder不处理的,由JavaBeanBinder创建
// 该类简单粗暴,直接使用默认的构造方法实例化
// 如果没有默认的,又不能被ValueObjectBinder处理,则会抛出异常
class JavaBeanBinder implements DataObjectBinder {
// 单例对象
public static final JavaBeanBinder INSTANCE = new JavaBeanBinder();
/**
* JavaBean对象绑定
*
* @param name 属性对应的key
* @param target 需要绑定的JavaBean对象类型
* @param context 绑定上下文信息
* @param propertyBinder 对于该JavaBean中内部的属性的绑定器
* @return 绑定后JavaBean对象
*/
public <T> T bind(ConfigurationPropertyName name, Bindable<T> target, Context context, DataObjectPropertyBinder propertyBinder) {
// 是否找到了可以绑定的属性
boolean hasKnownBindableProperties = target.getValue() != null && hasKnownBindableProperties(name, context);
// 生成目标JavaBean的类描述信息,就是可以反射操作该JavaBean的信息
Bean<T> bean = Bean.get(target, hasKnownBindableProperties);
// 如果没有给定JavaBean的实例对象,并且该JavaBean不可以实例化就不能绑定
if (bean == null) {
return null;
}
// 获取JavaBean对象的实例对象提供者,会返回一个JavaBean的对象
BeanSupplier<T> beanSupplier = bean.getSupplier(target);
// 开始给该JavaBean进行绑定
boolean bound = bind(propertyBinder, bean, beanSupplier);
// 如果绑定成功,返回该JavaBean对象的实例,否则返回false
return (bound ? beanSupplier.get() : null);
}
/**
* 绑定给定的JavaBean对象
*
* @param beanSupplier JavaBean对象的提供者,会提供该JavaBean的实例对象
* @param propertyBinder 对该JavaBean内部属性的绑定器
* @param bean 该JavaBean的描述信息(反射信息)
* @return 是否绑定成功
*/
public <T> boolean bind(DataObjectPropertyBinder propertyBinder, Bean<T> bean, BeanSupplier<T> beanSupplier) {
boolean bound = false;
// 遍历该JavaBean中缓存的所有属性值
for (BeanProperty beanProperty : bean.getProperties().values()) {
// 遍历所有的属性,一一绑定
bound |= bind(beanSupplier, propertyBinder, beanProperty);
}
return bound;
}
/**
* 绑定JavaBean中的属性
*
* @param beanSupplier JavaBean对象的提供者,会提供该JavaBean的实例对象
* @param propertyBinder 对该JavaBean内部属性的绑定器
* @param property 该JavaBean中内部属性的描述信息(反射信息)
* @return 是否绑定成功
*/
public <T> boolean bind(BeanSupplier<T> beanSupplier, DataObjectPropertyBinder propertyBinder, BeanProperty property) {
// 获取属性名和属性类型
String propertyName = property.getName();
ResolvableType type = property.getType();
// 执行该JavaBean的get方法,返回获取的值
Supplier<Object> value = property.getValue(beanSupplier);
// 获取属性注解
Annotation[] annotations = property.getAnnotations();
// 使用对象的属性绑定器对该JavaBean中内部的所有属性进行绑定
// 实际上就是对内部的属性进行递归绑定
// propertyBinder的源码上下,使用上一次对象的名称+当前正在绑定的属性名称的进行递归绑定
// DataObjectPropertyBinder propertyBinder = (propertyName, propertyTarget) -> bind(name.append(propertyName),propertyTarget, handler, context, false, false);
// 最终返回绑定后的属性结果对象
// 例如 A.b ==> 绑定a.b的时候,返回的是B对象
Object bound = propertyBinder.bindProperty(propertyName, Bindable.of(type).withSuppliedValue(value).withAnnotations(annotations));
// 该属性没有绑定到值
if (bound == null) {
// 绑定失败
return false;
}
// 获取到绑定的属性对象的值,并且存在set方法
if (property.isSettable()) {
// 调用set方法,设置属性值
property.setValue(beanSupplier, bound);
}
// 如果属性没有set方法,抛出异常
else if (value == null || !bound.equals(value.get())) {
throw new IllegalStateException("No setter found for property: " + property.getName());
}
return true;
}
// 描述一个JavaBean的类信息
class Bean {
// 一个JavaBean信息的缓存
public static Bean<?> cached;
// 当前Bean封装的ResolvableType类型
public final ResolvableType type;
// 当前Bean的解析类型,它正常情况都与type.getType一样,就是有一些特殊情况下,会对原始类型进行转换一下
// 所以它是解析后的类型,可以理解为就是该JavaBean的对象的类型
public final Class<?> resolvedType;
// 当前JavaBean的所有属性
public final Map<String, BeanProperty> properties = new LinkedHashMap<>();
Bean(ResolvableType type, Class<?> resolvedType) {
this.type = type;
this.resolvedType = resolvedType;
// 初始化该JavaBean的所有属性
addProperties(resolvedType);
}
// 初始化该JavaBean的所有属性
public void addProperties(Class<?> type) {
while (type != null && !Object.class.equals(type)) {
// 所有方法
Method[] declaredMethods = type.getDeclaredMethods();
// 所有字段
Field[] declaredFields = type.getDeclaredFields();
// 缓存该JavaBea的所有方法和字段信息
addProperties(declaredMethods, declaredFields);
// 解析父类
type = type.getSuperclass();
}
}
// 是否是符合条件的方法
// 私有的,Protected,Abstract,Static,Object的方法,Class的方法,代理方法都不满足条件
public boolean isCandidate(Method method) {
int modifiers = method.getModifiers();
// 私有的,Protected,Abstract,Static,Object的方法,Class的方法,代理方法都不满足条件
return !Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers) && !Modifier.isAbstract(modifiers)
&& !Modifier.isStatic(modifiers) && !Object.class.equals(method.getDeclaringClass())
&& !Class.class.equals(method.getDeclaringClass()) && method.getName().indexOf('$') == -1;
}
// 缓存该JavaBea的所有方法和字段信息
protected void addProperties(Method[] declaredMethods, Field[] declaredFields) {
for (int i = 0; i < declaredMethods.length; i++) {
if (!isCandidate(declaredMethods[i])) {
// 将该方法过滤
declaredMethods[i] = null;
}
}
// 找get/is方法,缓存到this.properties中
for (Method method : declaredMethods) {
addMethodIfPossible(method, "get", 0, BeanProperty::addGetter);
addMethodIfPossible(method, "is", 0, BeanProperty::addGetter);
}
// 找set方法,缓存到this.properties中
for (Method method : declaredMethods) {
addMethodIfPossible(method, "set", 1, BeanProperty::addSetter);
}
// 添加字段,缓存到this.properties中
for (Field field : declaredFields) {
addField(field);
}
}
// 获取JavaBean对象的实例对象提供者,会返回一个JavaBean的对象
public BeanSupplier<T> getSupplier(Bindable<T> target) {
return new BeanSupplier<>(() -> {
T instance = null;
// 如果存在JavaBean实例对象Supplier
if (target.getValue() != null) {
// 获取Supplier的JavaBean实例对象的值
instance = target.getValue().get();
}
// 如果给定了一个空的BeanSupplier,并没有在BeanSupplier返回JavaBean对象
if (instance == null) {
// 实例化该JavaBean对象
instance = (T) BeanUtils.instantiateClass(this.resolvedType);
}
// 返回JavaBean对象实例
return instance;
});
}
/**
* 获取JavaBean的包装类型Bean对象
*
* @param bindable 需要绑定的JavaBean对象的封装
* @param canCallGetValue 是否找到了可以绑定的属性值
*/
public static <T> Bean<T> get(Bindable<T> bindable, boolean canCallGetValue) {
// 获取JavaBean的类型
ResolvableType type = bindable.getType();
// 获取JavaBean的解析后的类型
Class<?> resolvedType = type.resolve(Object.class);
// 获取当前JavaBean对象的值
Supplier<T> value = bindable.getValue();
// JavaBean实例对象
T instance = null;
// 如果该对象找到了可以绑定的值,并且该JavaBean对象也不为空
if (canCallGetValue && value != null) {
// 获取到JavaBean对象
instance = value.get();
// 解析类型修改为真实类型(实例对象类型)
resolvedType = (instance != null) ? instance.getClass() : resolvedType;
}
// 如果JavaBean的实例对象为空,并且不可以实例化就不处理
if (instance == null && !isInstantiable(resolvedType)) {
return null;
}
// 是否存在该JavaBean的缓存的Bean信息
Bean<?> bean = Bean.cached;
// 如果没有缓存,或者需要绑定的类型与解析后的类型不是同一种类型
// 这两种情况都要重新缓存最新的JavaBean的类字段方法等信息
if (bean == null || !bean.isOfType(type, resolvedType)) {
// 创建Java的类描述信息对象
bean = new Bean<>(type, resolvedType);
// 缓存该Bean信息
cached = bean;
}
return (Bean<T>) bean;
}
}
// JavaBean的属性信息
public static class BeanProperty {
// 属性名
public final String name;
// 属性对应的JavaBean的类型
public final ResolvableType declaringClassType;
// 属性的get方法
public Method getter;
// 属性的set方法
public Method setter;
// 属性的字段信息
public Field field;
}
}
// 1: ValueObjectBinder
// 1.1. 该类不处理枚举,抽象类型
// 1.2. 之后再通过BindConstructorProvider类是否可以提供可用的构造方法
// BindConstructorProvider是一个抽象类,有不同的实现,但是作用都一样
// 就是只会处理构造方法只有一个,并且存在构造参数的情况,才会进行处理
// 2: JavaBeanBinder: ValueObjectBinder不处理的,由JavaBeanBinder创建
// 该类简单粗暴,直接使用默认的构造方法实例化
// 如果没有默认的,又不能被ValueObjectBinder处理,则会抛出异常
class ValueObjectBinder implements DataObjectBinder {
// 构造方法提供者
public final BindConstructorProvider constructorProvider;
ValueObjectBinder(BindConstructorProvider constructorProvider) {
this.constructorProvider = constructorProvider;
}
/**
* 通过给定的构造方法进行参数绑定
*/
@Override
public <T> T bind(ConfigurationPropertyName name, Bindable<T> target, Binder.Context context, DataObjectPropertyBinder propertyBinder) {
// 获取到绑定对象构造方法以及类型信息
DefaultValueObject<T> valueObject = DefaultValueObject.get(target, this.constructorProvider, context);
// 如果没有获取到可绑定的构造函数,则不处理
// 当前ValueObjectBinder只处理构造函数绑定的对象
if (valueObject == null) {
return null;
}
// 记录当前正在构造绑定的类型信息,这个可以判断是否存在多级构造绑定
context.pushConstructorBoundTypes(target.getType().resolve());
// 获取到构造方法对应的参数信息
List<ConstructorParameter> parameters = valueObject.getConstructorParameters();
// 参数值
List<Object> args = new ArrayList<>(parameters.size());
// 绑定状态
boolean bound = false;
// 遍历所有的构造参数信息
for (ConstructorParameter parameter : parameters) {
// 获取绑定的构造函数的值
Object arg = parameter.bind(propertyBinder) {
// name: 构造参数变量名
// type: 构造参数类型
// annotations: 构造参数上的注解信息
// 返回绑定的构造参数类型对象的值
return propertyBinder.bindProperty(this.name, Bindable.of(this.type).withAnnotations(this.annotations));
}
// 绑定成功标志
bound = bound || arg != null;
// 如果没有解析到参数,或者参数的默认值
Object defaultValue = parameter.getDefaultValue(context.getConverter()) {
// 获取参数上面是否存在@DefaultValue注解信息
for (Annotation annotation : this.annotations) {
if (annotation instanceof DefaultValue) {
// 对给定的值进行类型转换,转换为构造参数类型
return converter.convert(((DefaultValue) annotation).value(), this.type, this.annotations);
}
}
// 没有@DefaultValue注解信息,返回null
return null;
}
arg = (arg != null) ? arg : defaultValue;
// 保存绑定的构造参数
args.add(arg);
}
// 清空正在绑定的对象,因为已经绑定成功了
context.clearConfigurationProperty();
// 删除标记正在构造绑定的类型,因为已经绑定成功了
context.popConstructorBoundTypes();
// 使用构造参数实例化对象
return bound ? valueObject.instantiate(args) : null;
}
/**
* 创建对象
*/
@Override
public <T> T create(Bindable<T> target, Binder.Context context) {
// 获取到绑定对象构造方法以及类型信息
DefaultValueObject<T> valueObject = DefaultValueObject.get(target, this.constructorProvider, context);
// 如果没有获取到可绑定的构造函数,则不处理
// 当前ValueObjectBinder只处理构造函数绑定的对象
if (valueObject == null) {
return null;
}
// 获取构造函数参数
List<ConstructorParameter> parameters = valueObject.getConstructorParameters();
// 参数值
List<Object> args = new ArrayList<>(parameters.size());
// 遍历所有的参数
for (ConstructorParameter parameter : parameters) {
// 设置默认值
Object arg = parameter.getDefaultValue(context.getConverter()) {
// 获取参数上面是否存在@DefaultValue注解信息
for (Annotation annotation : this.annotations) {
if (annotation instanceof DefaultValue) {
// 对给定的值进行类型转换,转换为构造参数类型
return converter.convert(((DefaultValue) annotation).value(), this.type, this.annotations);
}
}
// 没有@DefaultValue注解信息,返回null
return null;
}
args.add(arg);
}
实例化
return valueObject.instantiate(args);
}
static class DefaultValueObject<T> {
// 实例化的构造方法
public final Constructor<T> constructor;
// 该对象的类型
public ResolvableType resolvableType;
// 变量名解析器
public static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
public DefaultValueObject(Constructor<T> constructor, ResolvableType type) {
this.constructor = constructor;
this.constructorParameters = parseConstructorParameters(constructor, type);
}
// 指定构造参数,实例化该对象
public T instantiate(List<Object> args) {
return BeanUtils.instantiateClass(this.constructor, args.toArray());
}
// 获取构造函数参数
public List<ConstructorParameter> getConstructorParameters() {
// 解析构造方法的变量名
String[] names = PARAMETER_NAME_DISCOVERER.getParameterNames(constructor);
// 获取构造函数参数名称
Parameter[] parameters = constructor.getParameters();
// 构造函数参数信息,包含了参数名,参数类型和注解信息
List<ConstructorParameter> result = new ArrayList<>(parameters.length);
// 遍历所有的参数
for (int i = 0; i < parameters.length; i++) {
String name = names[i];
// 获取参数的类型
ResolvableType parameterType = ResolvableType.forMethodParameter(new MethodParameter(constructor, i), type);
// 获取参数的注解信息
Annotation[] annotations = parameters[i].getDeclaredAnnotations();
// 将参数名,参数类型和注解信息封装成ConstructorParameter对象
result.add(new ConstructorParameter(name, parameterType, annotations));
}
return Collections.unmodifiableList(result);
}
/**
* 获取到绑定对象构造方法以及类型信息
*/
public static <T> ValueObject<T> get(Bindable<T> bindable, BindConstructorProvider constructorProvider, Binder.Context context) {
// 获取需要绑定对象的类型
Class<T> type = (Class<T>) bindable.getType().resolve();
// 如果是枚举或者抽象类不处理
if (type == null || type.isEnum() || Modifier.isAbstract(type.getModifiers())) {
return null;
}
// 使用构造方法提供者提供可用的构造方法
/**
* {@link DefaultBindConstructorProvider,ConfigurationPropertiesBindConstructorProvider}
*/
Constructor<?> bindConstructor = constructorProvider.getBindConstructor(bindable, context.isNestedConstructorBinding());
// 如果没有获取到可绑定的构造函数,则不处理
if (bindConstructor == null) {
return null;
}
// 将构造函数和当前绑定对象的类型封装为DefaultValueObject
return DefaultValueObject.get(bindConstructor, bindable.getType());
}
// 将构造函数和当前绑定对象的类型封装为DefaultValueObject
static <T> ValueObject<T> get(Constructor<?> bindConstructor, ResolvableType type) {
// 将构造函数和当前绑定对象的类型封装为DefaultValueObject
return new DefaultValueObject<>((Constructor<T>) bindConstructor, type);
}
}
}
// 默认的构造方法提供者
// 只返回该对象仅存在一个构造方法的有参构造,其他场景不处理
class DefaultBindConstructorProvider implements BindConstructorProvider {
/**
* 查找可以绑定的构造方法
*
* @param bindable 需要绑定目标对象
* @param isNestedConstructorBinding 是否支持嵌套绑定
* @return 绑定的构造方法
*/
public Constructor<?> getBindConstructor(Bindable<?> bindable, boolean isNestedConstructorBinding) {
// 获取需要绑定的类型
Class<?> type = bindable.getType().resolve();
// 如果绑定的实例对象不为空,或者绑定的类型为空,就不需要处理
// 这两种情况是: 1: 已经生成好了实例对象,所以没有必要再找构造方法
// 2. 没有获取到类型,则无法创建对象
if (bindable.getValue() != null || type == null) {
return null;
}
// 获取所有的构造方法
Constructor<?>[] constructors = type.getDeclaredConstructors();
// 如果只有一个构造方法,并且参数个数大于0,表示对象需要通过属性注入进行创建实例对象
if (constructors.length == 1 && constructors[0].getParameterCount() > 0) {
return constructors[0];
}
// 不是只有一个有参构造的情况,都返回null
return null;
}
}
// @ConfigurationProperties注解的构造方法提供者
class ConfigurationPropertiesBindConstructorProvider implements BindConstructorProvider {
// 单例对象
static final ConfigurationPropertiesBindConstructorProvider INSTANCE = new ConfigurationPropertiesBindConstructorProvider();
/**
* 查找可以绑定的构造方法
*
* @param bindable 需要绑定目标对象
* @param isNestedConstructorBinding 是否支持嵌套绑定
* @return 绑定的构造方法
*/
public Constructor<?> getBindConstructor(Bindable<?> bindable, boolean isNestedConstructorBinding) {
return getBindConstructor(bindable.getType().resolve(), isNestedConstructorBinding);
}
// 查找可以绑定的构造方法
public Constructor<?> getBindConstructor(Class<?> type, boolean isNestedConstructorBinding) {
// 查找标注了@ConstructorBinding的构造方法
Constructor<?> constructor = findConstructorBindingAnnotatedConstructor(type);
// 如果不存在@ConstructorBinding的构造方法
// 继续判断类的父类中存在该注解,或者支持嵌套构造绑定,这样就需要再次找可用的构造方法
if (constructor == null && (isConstructorBindingAnnotatedType(type) || isNestedConstructorBinding)) {
// 查找只有一个有参构造方法情况,如果有则返回,如果没有返回null
constructor = deduceBindConstructor(type);
}
return constructor;
}
// 查找标注了@ConstructorBinding的构造方法
public Constructor<?> findConstructorBindingAnnotatedConstructor(Class<?> type) {
// 获取该类的所有构造方法进行筛序
return findAnnotatedConstructor(type, type.getDeclaredConstructors());
}
// 从类中所有的构造方法中筛选标注了@ConstructorBinding的构造方法
public Constructor<?> findAnnotatedConstructor(Class<?> type, Constructor<?>... candidates) {
Constructor<?> constructor = null;
for (Constructor<?> candidate : candidates) {
if (MergedAnnotations.from(candidate).isPresent(ConstructorBinding.class)) {
// 如果存在@ConstructorBinding注解,就必须要有参数
Assert.state(candidate.getParameterCount() > 0, type.getName() + " declares @ConstructorBinding on a no-args constructor");
// constructor只有第一次进才为空,如果不为空,表示存在多个标注了@ConstructorBinding的构造方法
Assert.state(constructor == null, type.getName() + " has more than one @ConstructorBinding constructor");
// 找到了可用的@ConstructorBinding构造方法
constructor = candidate;
}
}
return constructor;
}
// 类的父类中是否存在该注解
public boolean isConstructorBindingAnnotatedType(Class<?> type) {
return MergedAnnotations.from(type, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES).isPresent(ConstructorBinding.class);
}
// 查找只有一个有参构造方法情况,如果有则返回,如果没有返回null
public Constructor<?> deduceBindConstructor(Class<?> type) {
// 获取所有的构造方法
Constructor<?>[] constructors = type.getDeclaredConstructors();
// 如果构造方法只有一个有参构造方法,直接返回
if (constructors.length == 1 && constructors[0].getParameterCount() > 0) {
return constructors[0];
}
// 否则不处理
return null;
}
}
}
// 配置属性源,一般是从配置文件中加载的属性
class ConfigurationPropertySources {
// 附加"configurationProperties"的配置属性
public static void attach(Environment environment) {
// 获取上下文环境中所有的属性对象
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
// 是否存在configurationProperties名称对应的属性对象
PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
// 如果存在configurationProperties名称对应的属性对象,并且之前的数据与现在要保存的数据不一样
if (attached != null && attached.getSource() != sources) {
// 删除原来的数据
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
// 置空
attached = null;
}
// 如果没有附加上configurationProperties属性
if (attached == null) {
// 使用configurationProperties作为name,保存一个ConfigurationPropertySourcesPropertySource属性源,并且source数据为SpringConfigurationPropertySources
sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME, new SpringConfigurationPropertySources(sources)));
}
}
public static Iterable<ConfigurationPropertySource> from(Iterable<PropertySource<?>> sources) {
// 返回普通的Spring属性配置源
return new SpringConfigurationPropertySources(sources);
}
public static Iterable<ConfigurationPropertySource> from(PropertySource<?> source) {
SpringConfigurationPropertySource propertySource = SpringConfigurationPropertySource.from(source) {
// 如果当前配置元素是可枚举迭代的
if (isFullEnumerable(source)) {
// 返回可以迭代的ConfigurationPropertySource
return new SpringIterableConfigurationPropertySource((EnumerablePropertySource<?>) source, mapper);
}
// 返回普通的Spring属性配置源
return new SpringConfigurationPropertySource(source);
}
return Collections.singleton(propertySource);
}
}