SpringBoot启动流程源码分析( 五 )

复制
PropertySourcesPlaceholdersResolver类构造函数public PropertySourcesPlaceholdersResolver(Environment environment) {this(getSources(environment), (PropertyPlaceholderHelper)null);}public PropertySourcesPlaceholdersResolver(Iterable<PropertySource<?>> sources, PropertyPlaceholderHelper helper) {this.sources = sources;// 属性占位符解析器会去解析"${" 和 "}"两个符号包裹的环境变量this.helper = helper != null ? helper : new PropertyPlaceholderHelper("${", "}", ":", true);}复制
PropertySourcesPlaceholdersResolver#getSources方法private static PropertySources getSources(Environment environment) {// 断言environment不为空Assert.notNull(environment, "Environment must not be null");// 断言environment是一个ConfigurableEnvironment类实例Assert.isInstanceOf(ConfigurableEnvironment.class, environment, "Environment must be a ConfigurableEnvironment");return ((ConfigurableEnvironment)environment).getPropertySources();}复制
ConfigurationPropertySources#attach方法public static void attach(Environment environment) {Assert.isInstanceOf(ConfigurableEnvironment.class, environment);// 从环境变量中获取多属性配置源MutablePropertySources sources = ((ConfigurableEnvironment)environment).getPropertySources();PropertySource<?> attached = sources.get("configurationProperties");if (attached != null && attached.getSource() != sources) {// 若attached且attach#getSource得到的结果不等于sources , 则删除sources中configurationProperties对应的键值对并置空attachedsources.remove("configurationProperties");attached = null;}if (attached == null) {// 若attached为空则构建新的属性源并添加到sources的属性源列表的第一个位置sources.addFirst(new ConfigurationPropertySourcesPropertySource("configurationProperties", new SpringConfigurationPropertySources(sources)));}}复制
Binder#bind方法public <T> BindResult<T> bind(String name, Bindable<T> target) {return this.bind((ConfigurationPropertyName)ConfigurationPropertyName.of(name), target, (BindHandler)null);}public <T> BindResult<T> bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler) {Assert.notNull(name, "Name must not be null");Assert.notNull(target, "Target must not be null");handler = handler != null ? handler : BindHandler.DEFAULT;Binder.Context context = new Binder.Context();T bound = this.bind(name, target, handler, context, false);return BindResult.of(bound);}protected final <T> T bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Binder.Context context, boolean allowRecursiveBinding) {context.clearConfigurationProperty();try {target = handler.onStart(name, target, context);if (target == null) {return null;} else {Object bound = this.bindObject(name, target, handler, context, allowRecursiveBinding);return this.handleBindResult(name, target, handler, context, bound);}} catch (Exception var7) {return this.handleBindError(name, target, handler, context, var7);}}// 绑定对象private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Binder.Context context, boolean allowRecursiveBinding) {ConfigurationProperty property = this.findProperty(name, context);if (property == null && this.containsNoDescendantOf(context.getSources(), name)) {return null;} else {AggregateBinder<?> aggregateBinder = this.getAggregateBinder(target, context);if (aggregateBinder != null) {return this.bindAggregate(name, target, handler, context, aggregateBinder);} else if (property != null) {try {return this.bindProperty(target, context, property);} catch (ConverterNotFoundException var10) {Object bean = this.bindBean(name, target, handler, context, allowRecursiveBinding);if (bean != null) {return bean;} else {throw var10;}}} else {return this.bindBean(name, target, handler, context, allowRecursiveBinding);}}}private <T> Object bindProperty(Bindable<T> target, Binder.Context context, ConfigurationProperty property) {context.setConfigurationProperty(property);Object result = property.getValue();// 使用占位符解析器解析属性占位符result = this.placeholdersResolver.resolvePlaceholders(result);// 从context中获取转换器转换resultresult = context.getConverter().convert(result, target);return result;}

经验总结扩展阅读