Spring,SpringBoot配置属性的绑定实现原理

// 配置文件属性绑定器
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);
    }
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值