三里面代码跟到了准备环境这个地方,按照一贯的思路,应该也是发个event出去,然后各个监听的listener做自己的事
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
继续的跟下去
/**
* Template method delegating to
// 很简单是两个方法的模板方法,用这样的order来执行
* {@link #configurePropertySources(ConfigurableEnvironment, String[])} and
* {@link #configureProfiles(ConfigurableEnvironment, String[])} in that order.
* Override this method for complete control over Environment customization, or one of
* the above for fine-grained control over property sources or profiles, respectively.
* @param environment this application's environment
* @param args arguments passed to the {@code run} method
* @see #configureProfiles(ConfigurableEnvironment, String[])
* @see #configurePropertySources(ConfigurableEnvironment, String[])
*/
protected void configureEnvironment(ConfigurableEnvironment environment,
String[] args) {
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
继续的跟进去这两个方法
主要看这个吧
configureProfiles(environment, args);
/**
// 原来可以active profiles 等于说可以active多个profile 都封装在environment对象
//里面 看代码使用空格分割各个profile就可以了
* Configure which profiles are active (or active by default) for this application
* environment. Additional profiles may be activated during configuration file
* processing via the {@code spring.profiles.active} property.
* @param environment this application's environment
* @param args arguments passed to the {@code run} method
* @see #configureEnvironment(ConfigurableEnvironment, String[])
* @see org.springframework.boot.context.config.ConfigFileApplicationListener
*/
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
environment.getActiveProfiles(); // ensure they are initialized
// But these ones should go first (last wins in a property key clash)
Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}
ok,通过这个方法找到了profiles文件,接下来就是发event了,果然发了个ApplicationEnvironmentPreparedEvent,我的项目里面一共有11个listener监听了这个event,如下
首先看 感觉这个设计的真是奇妙
public class BootstrapApplicationListener
implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered
做的事情:
1看是否开启了spring.cloud.bootstrap.enabled 没有没有设置就设置成true,如果手动的关掉,直接的return
2 加载在配置文件配置好的List<String> names = new ArrayList<>(SpringFactoriesLoader
.loadFactoryNames(BootstrapConfiguration.class, classLoader));
主要是config文件,如下
可以看到在构造ConfigurableApplicationContext的时候,
final ConfigurableApplicationContext context = builder.run();
这个调用又跑到了SpringApplication的run方法,这个是递归的嵌套调用,来生成一个context
第一次进来的时候
if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
return;
}
这个是false,第二次进来的时候这个又变成了true,然后会return,等于说BootstrapApplicationListener生成了一个初始化的context,然后又主导了其他所有的listener的过程。
再看
public class ConfigFileApplicationListener
implements EnvironmentPostProcessor, SmartApplicationListener, Ordered
这个listener主要加载配置文件,而所有加载配置文件的EnvironmentPostProcessor事先配置在META-INF/spring.factories里面,boot一共事先定义了6个,如下
所以可以看到其实所有的监听的ApplicationEnvironmentPreparedEvent的listener走了两遍。
ps:在boot加载bean之前,还没有bean,那这些listener哪里来的,都是配置在META-INF/spring.factories这个里面,所以自己写个ApplicationEnvironmentPreparedEvent的监听器是触发不了的,除非加到META-INF/spring.factories里面。