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

复制
前面的WebApplicationType#deduceFromClasspath方法码分析中我们知道返回的是一个SERVLET枚举 。因此,spring-boot项目中具有spring-boot-starter-web起步依赖时getOrCreateEnvironment方法返回的是一个StandardServletEnvironment实例
SpringApplicationRunListeners#environmentPrepared接下来我们进入SpringApplicationRunListeners#environmentPrepared方法
public void environmentPrepared(ConfigurableEnvironment environment) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();// 通过迭代遍历启动监听器发布环境准备事件listener.environmentPrepared(environment);}}复制
SpringApplication#bindToSpringApplication方法准备好环境后进入SpringApplication#bindToSpringApplication方法
protected void bindToSpringApplication(ConfigurableEnvironment environment) {try {Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));} catch (Exception var3) {throw new IllegalStateException("Cannot bind to SpringApplication", var3);}}复制
Binder#get方法public static Binder get(Environment environment) {// 这里传入了一个属性源占位符解析器类实例参数return new Binder(ConfigurationPropertySources.get(environment), new PropertySourcesPlaceholdersResolver(environment));}复制
Binder类构造方法public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver) {this(sources, placeholdersResolver, (ConversionService)null, (Consumer)null);}public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver, ConversionService conversionService, Consumer<PropertyEditorRegistry> propertyEditorInitializer) {Assert.notNull(sources, "Sources must not be null");this.sources = sources;this.placeholdersResolver = placeholdersResolver != null ? placeholdersResolver : PlaceholdersResolver.NONE;this.conversionService = conversionService != null ? conversionService : ApplicationConversionService.getSharedInstance();this.propertyEditorInitializer = propertyEditorInitializer;}复制
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;}

推荐阅读