前言
百度了下EnvironmentPostProcessor
没看到什么注释叫什么,那我在本文就称之为环境处理器好了。
在SpringBoot启动准备好环境后,将发布一个ApplicationEnvironmentPreparedEvent事件,而ConfigFileApplicationListener
侦听器就是这个事件的侦听者之一。当侦听者收到该事件时将执行对应的响应操作。
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
postProcessors.add(this);
AnnotationAwareOrderComparator.sort(postProcessors);
for (EnvironmentPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication());
}
}
下面就将加载配置好的环境处理器来工作。接着我们就来看看这些环境处理器吧:
这里可以看到配置文件中已经配置了4个环境处理器,然后看代码里面再讲当前侦听者加到了处理器集合中。接着用AnnotationAwareOrderComparator排了个序。
简单看下AnnotationAwareOrderComparator:
排完序后的样子:
紧接着这5个处理器开始处理上下文。
SystemEnvironmentPropertySourceEnvironmentPostProcessor
/**
* EnvironmentPostProcessor 提供一个可以跟踪每一个系统环境属性的SystemEnvironmentOrigin的OriginAwareSystemEnvironmentPropertySource来取代系统环境的SystemEnvironmentPropertySource。
* An {@link EnvironmentPostProcessor} that replaces the systemEnvironment
* {@link SystemEnvironmentPropertySource} with an
* {@link OriginAwareSystemEnvironmentPropertySource} that can track the
* {@link SystemEnvironmentOrigin} for every system environment property.
*
* @author Madhura Bhave
* @since 2.0.0
*/
public class SystemEnvironmentPropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
翻译起来感觉好绕口,然后有抛出好多问号????。但是看了下这几个类的注释,感觉不好解释,目前也没多大的研究价值,所以暂时不贴了。有兴趣自己去看看注释。
继续看他的postProcessEnvironment方法:
/** System environment property source name: {@value}. */
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String sourceName = StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME;
PropertySource<?> propertySource = environment.getPropertySources().get(sourceName);
if (propertySource != null) {
replacePropertySource(environment, sourceName, propertySource);
}
}
从环境中获取属性源集合,并获取系统环境属性(systemEnvironment),然后替换掉环境 中的systemEnvironment。
wath???脱了裤子然后又穿回去?难道更漂亮了???
看先看脱的时候怎么脱的:
public MutablePropertySources getPropertySources() {
return this.propertySources;
}
public PropertySource<?> get(String name) {
int index = this.propertySourceList.indexOf(PropertySource.named(name));
return (index != -1 ? this.propertySourceList.get(index) : null);
}
脱的时候没啥花把式啊,就是从propertySourceList里面拿出来啊。
再看下穿回去干了啥:
private void replacePropertySource(ConfigurableEnvironment environment, String sourceName,
PropertySource<?> propertySource) {
Map<String, Object> originalSource = (Map<String, Object>) propertySource.getSource();
SystemEnvironmentPropertySource source = new OriginAwareSystemEnvironmentPropertySource(sourceName,
originalSource);
environment.getPropertySources().replace(sourceName, source);
}
public void replace(String name, PropertySource<?> propertySource) {
int index = assertPresentAndGetIndex(name);
this.propertySourceList.set(index, propertySource);
}
好像就换了个SystemEnvironmentPropertySource,看看原来的SystemEnvironmentPropertySource 是什么:
哦~~,原来是换了条裤儿穿哦。
好了这个处理器看完了,就是换个带OriginLookup的裤子。
SpringApplicationJsonEnvironmentPostProcessor
/**
* An {@link EnvironmentPostProcessor} that parses JSON from
* {@code spring.application.json} or equivalently {@code SPRING_APPLICATION_JSON} and
* adds it as a map property source to the {@link Environment}. The new properties are
* added with higher priority than the system properties.
*
* @author Dave Syer
* @author Phillip Webb
* @author Madhura Bhave
* @author Artsiom Yudovin
* @since 1.3.0
*/
public class SpringApplicationJsonEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
感觉不太好翻译,就不翻译了,反正就是用来配置解析JSON的东西。
看下postProcessEnvironment方法:
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.stream().map(JsonPropertyValue::get).filter(Objects::nonNull).findFirst()
.ifPresent((v) -> processJson(environment, v));
}
static JsonPropertyValue get(PropertySource<?> propertySource) {
for (String candidate : CANDIDATES) {
Object value = propertySource.getProperty(candidate);
if (value instanceof String && StringUtils.hasLength((String) value)) {
return new JsonPropertyValue(propertySource, candidate, (String) value);
}
}
return null;
}
private static final String[] CANDIDATES = { SPRING_APPLICATION_JSON_PROPERTY,
SPRING_APPLICATION_JSON_ENVIRONMENT_VARIABLE };
/**
* Name of the {@code spring.application.json} property.
*/
public static final String SPRING_APPLICATION_JSON_PROPERTY = "spring.application.json";`/**
* Name of the {@code SPRING_APPLICATION_JSON} environment variable.
*/
public static final String SPRING_APPLICATION_JSON_ENVIRONMENT_VARIABLE = "SPRING_APPLICATION_JSON";
从环境中获取配置的源里面获取spring.application.json和SPRING_APPLICATION_JSON属性配置,然后取第一个执行下面这个方法:
private void processJson(ConfigurableEnvironment environment, JsonPropertyValue propertyValue) {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> map = parser.parseMap(propertyValue.getJson());
if (!map.isEmpty()) {
addJsonPropertySource(environment, new JsonPropertySource(propertyValue, flatten(map)));
}
}
这个有点没理解到,百度了下,看了些文章大概理解了下,也就是说我们可以在环境变量里面通过设置spring.application.json来配置属性值。
牛刀小试:
还真可以,再回去看刚才的注释,貌似懂了点了,而且这个不一定配置再启动项上面,还可以配置再系统环境里面。一般人估计不会用到,用得到的不是一般人。我就是一般人,所以就先过了。
CloudFoundryVcapEnvironmentPostProcessor
/**
* An {@link EnvironmentPostProcessor} that knows where to find VCAP (a.k.a. Cloud
* Foundry) meta data in the existing environment. It parses out the VCAP_APPLICATION and
* VCAP_SERVICES meta data and dumps it in a form that is easily consumed by
* {@link Environment} users. If the app is running in Cloud Foundry then both meta data
* items are JSON objects encoded in OS environment variables. VCAP_APPLICATION is a
* shallow hash with basic information about the application (name, instance id, instance
* index, etc.), and VCAP_SERVICES is a hash of lists where the keys are service labels
* and the values are lists of hashes of service instance meta data. Examples are:
*
* <pre class="code">
* VCAP_APPLICATION: {"instance_id":"2ce0ac627a6c8e47e936d829a3a47b5b","instance_index":0,
* "version":"0138c4a6-2a73-416b-aca0-572c09f7ca53","name":"foo",
* "uris":["foo.cfapps.io"], ...}
* VCAP_SERVICES: {"rds-mysql-1.0":[{"name":"mysql","label":"rds-mysql-1.0","plan":"10mb",
* "credentials":{"name":"d04fb13d27d964c62b267bbba1cffb9da","hostname":"mysql-service-public.clqg2e2w3ecf.us-east-1.rds.amazonaws.com",
* "host":"mysql-service-public.clqg2e2w3ecf.us-east-1.rds.amazonaws.com","port":3306,"user":"urpRuqTf8Cpe6",
* "username":"urpRuqTf8Cpe6","password":"pxLsGVpsC9A5S"}
* }]}
* </pre>
*
* These objects are flattened into properties. The VCAP_APPLICATION object goes straight
* to {@code vcap.application.*} in a fairly obvious way, and the VCAP_SERVICES object is
* unwrapped so that it is a hash of objects with key equal to the service instance name
* (e.g. "mysql" in the example above), and value equal to that instances properties, and
* then flattened in the same way. E.g.
*
* <pre class="code">
* vcap.application.instance_id: 2ce0ac627a6c8e47e936d829a3a47b5b
* vcap.application.version: 0138c4a6-2a73-416b-aca0-572c09f7ca53
* vcap.application.name: foo
* vcap.application.uris[0]: foo.cfapps.io
*
* vcap.services.mysql.name: mysql
* vcap.services.mysql.label: rds-mysql-1.0
* vcap.services.mysql.credentials.name: d04fb13d27d964c62b267bbba1cffb9da
* vcap.services.mysql.credentials.port: 3306
* vcap.services.mysql.credentials.host: mysql-service-public.clqg2e2w3ecf.us-east-1.rds.amazonaws.com
* vcap.services.mysql.credentials.username: urpRuqTf8Cpe6
* vcap.services.mysql.credentials.password: pxLsGVpsC9A5S
* ...
* </pre>
*
* N.B. this initializer is mainly intended for informational use (the application and
* instance ids are particularly useful). For service binding you might find that Spring
* Cloud is more convenient and more robust against potential changes in Cloud Foundry.
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Madhura Bhave
* @since 1.3.0
*/
public class CloudFoundryVcapEnvironmentPostProcessor
implements EnvironmentPostProcessor, Ordered, ApplicationListener<ApplicationPreparedEvent> {
这么多注释看起来头都大了。还提及到了上面VCAP,闻所未闻。先看下postProcessEnvironment方法:
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
if (CloudPlatform.CLOUD_FOUNDRY.isActive(environment)) {
Properties properties = new Properties();
JsonParser jsonParser = JsonParserFactory.getJsonParser();
addWithPrefix(properties, getPropertiesFromApplication(environment, jsonParser), "vcap.application.");
addWithPrefix(properties, getPropertiesFromServices(environment, jsonParser), "vcap.services.");
MutablePropertySources propertySources = environment.getPropertySources();
if (propertySources.contains(CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME)) {
propertySources.addAfter(CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME,
new PropertiesPropertySource("vcap", properties));
}
else {
propertySources.addFirst(new PropertiesPropertySource("vcap", properties));
}
}
}
只有isActive为true才会执行,看下判断依据:
/**
* Cloud Foundry platform.
*/
CLOUD_FOUNDRY {
@Override
public boolean isActive(Environment environment) {
return environment.containsProperty("VCAP_APPLICATION") || environment.containsProperty("VCAP_SERVICES");
}
},
需要再环境变量里面配置VCAP_APPLICATION
或VCAP_SERVICES
,我很清楚,没遇见过,超纲内容,先跳过。
ConfigFileApplicationListener
这个就是我们的侦听者,不过他同时是一个处理器罢了,直接看postProcessEnvironment方法:
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
addPropertySources(environment, application.getResourceLoader());
}
/**
添加配置文件属性源到指定的环境
* @param environment the environment to add source to
* @param resourceLoader the resource loader
* @see #addPostProcessors(ConfigurableApplicationContext)
*/
protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
RandomValuePropertySource.addToEnvironment(environment);
new Loader(environment, resourceLoader).load();
}
/**
* {@link PropertySource} that returns a random value for any property that starts with
* {@literal "random."}. Where the "unqualified property name" is the portion of the
* requested property name beyond the "random." prefix, this {@link PropertySource}
* returns:
* <ul>
* <li>When {@literal "int"}, a random {@link Integer} value, restricted by an optionally
* specified range.</li>
* <li>When {@literal "long"}, a random {@link Long} value, restricted by an optionally
* specified range.</li>
* <li>Otherwise, a {@code byte[]}.</li>
* </ul>
* The {@literal "random.int"} and {@literal "random.long"} properties supports a range
* suffix whose syntax is:
* <p>
* {@code OPEN value (,max) CLOSE} where the {@code OPEN,CLOSE} are any character and
* {@code value,max} are integers. If {@code max} is provided then {@code value} is the
* minimum value and {@code max} is the maximum (exclusive).
*
* @author Dave Syer
* @author Matt Benson
* @since 1.0.0
*/
public class RandomValuePropertySource extends PropertySource<Random> {
public static void addToEnvironment(ConfigurableEnvironment environment) {
environment.getPropertySources().addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
new RandomValuePropertySource(RANDOM_PROPERTY_SOURCE_NAME));
logger.trace("RandomValuePropertySource add to Environment");
}
/**
* Add the given property source object with precedence immediately lower
* than the named relative property source.
*/
public void addAfter(String relativePropertySourceName, PropertySource<?> propertySource) {
assertLegalRelativeAddition(relativePropertySourceName, propertySource);
removeIfPresent(propertySource);
int index = assertPresentAndGetIndex(relativePropertySourceName);
addAtIndex(index + 1, propertySource);
}
貌似就是把原有的systemEnvironment搞一个随机后缀,然后放到其后,然后重新加载一下,不是很明白这个操作在干嘛。
new Loader(environment, resourceLoader).load();
在生成随机前缀的环境变量后,执行了一个load操作,这行代码很不起眼,我都给漏掉了,还是我带着‘spring是何时指定application加载配置属性的’这个疑问来找才看到的。接下来看下load操作干什么:
private static final String DEFAULT_PROPERTIES = "defaultProperties";
private static final Set<String> LOAD_FILTERED_PROPERTY;
static {
Set<String> filteredProperties = new HashSet<>();
filteredProperties.add("spring.profiles.active");
filteredProperties.add("spring.profiles.include");
LOAD_FILTERED_PROPERTY = Collections.unmodifiableSet(filteredProperties);
}
void load() {
FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
(defaultProperties) -> {
this.profiles = new LinkedList<>();
this.processedProfiles = new LinkedList<>();
this.activatedProfiles = false;
this.loaded = new LinkedHashMap<>();
initializeProfiles();
while (!this.profiles.isEmpty()) {
Profile profile = this.profiles.poll();
if (isDefaultProfile(profile)) {
addProfileToEnvironment(profile.getName());
}
load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
}
load(null, this::getNegativeProfileFilter, addToLoaded(MutablePropertySources::addFirst, true));
addLoadedPropertySources();
applyActiveProfiles(defaultProperties);
});
}
static void apply(ConfigurableEnvironment environment, String propertySourceName, Set<String> filteredProperties,
Consumer<PropertySource<?>> operation) {
MutablePropertySources propertySources = environment.getPropertySources();
PropertySource<?> original = propertySources.get(propertySourceName);
if (original == null) {
operation.accept(null);
return;
}
propertySources.replace(propertySourceName, new FilteredPropertySource(original, filteredProperties));
try {
operation.accept(original);
}
finally {
propertySources.replace(propertySourceName, original);
}
}
从先前准备的环境中取出defaultProperties配置,如果没有获取到,则消费上面定义的方法。
这里记忆中并没有配置defaultProperties环境,debug也显示确实没有,所以先看看上面那个处理过程:
initializeProfiles
/**
* Initialize profile information from both the {@link Environment} active
* profiles and any {@code spring.profiles.active}/{@code spring.profiles.include}
* properties that are already set.
*/
private void initializeProfiles() {
// The default profile for these purposes is represented as null. We add it
// first so that it is processed first and has lowest priority.
this.profiles.add(null);
Set<Profile> activatedViaProperty = getProfilesFromProperty(ACTIVE_PROFILES_PROPERTY);
Set<Profile> includedViaProperty = getProfilesFromProperty(INCLUDE_PROFILES_PROPERTY);
List<Profile> otherActiveProfiles = getOtherActiveProfiles(activatedViaProperty, includedViaProperty);
this.profiles.addAll(otherActiveProfiles);
// Any pre-existing active profiles set via property sources (e.g.
// System properties) take precedence over those added in config files.
this.profiles.addAll(includedViaProperty);
addActiveProfiles(activatedViaProperty);
if (this.profiles.size() == 1) { // only has null profile
for (String defaultProfileName : this.environment.getDefaultProfiles()) {
Profile defaultProfile = new Profile(defaultProfileName, true);
this.profiles.add(defaultProfile);
}
}
}
private Set<Profile> getProfilesFromProperty(String profilesProperty) {
if (!this.environment.containsProperty(profilesProperty)) {
return Collections.emptySet();
}
Binder binder = Binder.get(this.environment);
Set<Profile> profiles = getProfiles(binder, profilesProperty);
return new LinkedHashSet<>(profiles);
}
private Set<Profile> getProfiles(Binder binder, String name) {
return binder.bind(name, STRING_ARRAY).map(this::asProfileSet).orElse(Collections.emptySet());
}
private List<Profile> getOtherActiveProfiles(Set<Profile> activatedViaProperty,
Set<Profile> includedViaProperty) {
return Arrays.stream(this.environment.getActiveProfiles()).map(Profile::new).filter(
(profile) -> !activatedViaProperty.contains(profile) && !includedViaProperty.contains(profile))
.collect(Collectors.toList());
}
先根据spring.profiles.active
配置和spring.profiles.include
获取配置的激活配置文件,然后再从环境中获取别的配置文件,最终将三者全部追加到profiles中。如果最终profiles中都只有null节点,那么就获取默认的配置文件。
我们一般把spring.profiles.active配置在application.yml或application.properties里面,这个时候都还没加载这两个配置文件,拿着地方指的是我们可通过配置
spring.profiles.active
和spring.profiles.include
来修改激活文件位置,而不用去application里面配置??
/**
* Return the set of default profiles explicitly set via
* {@link #setDefaultProfiles(String...)} or if the current set of default profiles
* consists only of {@linkplain #getReservedDefaultProfiles() reserved default
* profiles}, then check for the presence of the
* {@value #DEFAULT_PROFILES_PROPERTY_NAME} property and assign its value (if any)
* to the set of default profiles.
* @see #AbstractEnvironment()
* @see #getDefaultProfiles()
* @see #DEFAULT_PROFILES_PROPERTY_NAME
* @see #getReservedDefaultProfiles()
*/
protected Set<String> doGetDefaultProfiles() {
synchronized (this.defaultProfiles) {
if (this.defaultProfiles.equals(getReservedDefaultProfiles())) {
String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
if (StringUtils.hasText(profiles)) {
setDefaultProfiles(StringUtils.commaDelimitedListToStringArray(
StringUtils.trimAllWhitespace(profiles)));
}
}
return this.defaultProfiles;
}
}
这里地方实属看不懂为什么。
profiles加载完后,紧接着就是去找配置文件的位置,看下private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer)
方法:
private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
getSearchLocations().forEach((location) -> {
boolean isFolder = location.endsWith("/");
Set<String> names = isFolder ? getSearchNames() : NO_SEARCH_NAMES;
names.forEach((name) -> load(location, name, profile, filterFactory, consumer));
});
}
/**
* The "config location" property name.
*/
public static final String CONFIG_LOCATION_PROPERTY = "spring.config.location";
//这里貌似可以通过配置spring.config.location来修改配置文件的搜索路径?
private Set<String> getSearchLocations() {
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
return getSearchLocations(CONFIG_LOCATION_PROPERTY);
}
Set<String> locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
locations.addAll(
asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
return locations;
}
private Set<String> getSearchLocations(String propertyName) {
Set<String> locations = new LinkedHashSet<>();
if (this.environment.containsProperty(propertyName)) {
for (String path : asResolvedSet(this.environment.getProperty(propertyName), null)) {
if (!path.contains("$")) {
path = StringUtils.cleanPath(path);
if (!ResourceUtils.isUrl(path)) {
path = ResourceUtils.FILE_URL_PREFIX + path;
}
}
locations.add(path);
}
}
return locations;
}
这个地方得到4个路径如下,接着在这4个路径下去找配置的spring.config.name
对应的配置文件,如果没有则返回默认的配置文件名称application
;
private static final String DEFAULT_NAMES = "application";
/**
* The "config name" property name.
*/
public static final String CONFIG_NAME_PROPERTY = "spring.config.name";
private Set<String> getSearchNames() {
if (this.environment.containsProperty(CONFIG_NAME_PROPERTY)) {
String property = this.environment.getProperty(CONFIG_NAME_PROPERTY);
return asResolvedSet(property, null);
}
return asResolvedSet(ConfigFileApplicationListener.this.names, DEFAULT_NAMES);
}
spring.config.location这个属性说好像是对运维的支撑,有兴趣可以自行百度
紧接着执行private void load(String location, String name, Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer)
方法加载:
private void load(String location, String name, Profile profile, DocumentFilterFactory filterFactory,
DocumentConsumer consumer) {
if (!StringUtils.hasText(name)) {
for (PropertySourceLoader loader : this.propertySourceLoaders) {
if (canLoadFileExtension(loader, location)) {
load(loader, location, profile, filterFactory.getDocumentFilter(profile), consumer);
return;
}
}
throw new IllegalStateException("File extension of config file location '" + location
+ "' is not known to any PropertySourceLoader. If the location is meant to reference "
+ "a directory, it must end in '/'");
}
Set<String> processed = new HashSet<>();
for (PropertySourceLoader loader : this.propertySourceLoaders) {
for (String fileExtension : loader.getFileExtensions()) {
if (processed.add(fileExtension)) {
loadForFileExtension(loader, location + name, "." + fileExtension, profile, filterFactory,
consumer);
}
}
}
}
这个地方配置源加载器有两个,properties和yaml,刚好可以加载application.properties和application.yml两个配置文件。实际上properties可以加载properties和xml两种,application可以加载yml和yaml两种配置文件。
addLoadedPropertySources
经过上面一系列操作,反正是把配置文件加载完了,现在看看addLoadedPropertySources这个方法高了上面,没注释,从名字大概猜是把刚才加载的属性源文件加到哪里去。
private void addLoadedPropertySources() {
// 目标是ConfigurableEnvironment的属性源
MutablePropertySources destination = this.environment.getPropertySources();
//拷贝对象是刚才加载的一些MutablePropertySources
List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values());
//把属性源排个序
Collections.reverse(loaded);
String lastAdded = null;
Set<String> added = new HashSet<>();
for (MutablePropertySources sources : loaded) {
for (PropertySource<?> source : sources) {
if (added.add(source.getName())) {
//从配置文件中读取属性以此往ConfigurableEnvironment里面扔
addLoadedPropertySource(destination, lastAdded, source);
lastAdded = source.getName();
}
}
}
}
private void addLoadedPropertySource(MutablePropertySources destination, String lastAdded,
PropertySource<?> source) {
if (lastAdded == null) {
if (destination.contains(DEFAULT_PROPERTIES)) {
//设置当前属性优先级高于defaultProperties
destination.addBefore(DEFAULT_PROPERTIES, source);
}
else {
//设置当前属性级别最低
destination.addLast(source);
}
}
else {
//级别低于上一个属性
destination.addAfter(lastAdded, source);
}
}
这里的感觉就是能看懂每行代码,但是看起还是有点晕乎乎的了,先这样吧,根据debug来看,这个地方已经把我们配置的两个配置文件加进去了。
applyActiveProfiles
看名字的意思是应用激活的配置文件:
private void applyActiveProfiles(PropertySource<?> defaultProperties) {
List<String> activeProfiles = new ArrayList<>();
if (defaultProperties != null) {
Binder binder = new Binder(ConfigurationPropertySources.from(defaultProperties),
new PropertySourcesPlaceholdersResolver(this.environment));
activeProfiles.addAll(getDefaultProfiles(binder, "spring.profiles.include"));
if (!this.activatedProfiles) {
activeProfiles.addAll(getDefaultProfiles(binder, "spring.profiles.active"));
}
}
this.processedProfiles.stream().filter(this::isDefaultProfile).map(Profile::getName)
.forEach(activeProfiles::add);
this.environment.setActiveProfiles(activeProfiles.toArray(new String[0]));
}
至此,ConfigFileApplicationListener的操作完成了。
DebugAgentEnvironmentPostProcessor
/**
* {@link EnvironmentPostProcessor} to enable the Reactor Debug Agent if available.
* <p>
* The debug agent is enabled by default, unless the
* {@code "spring.reactor.debug-agent.enabled"} configuration property is set to false. We
* are using here an {@link EnvironmentPostProcessor} instead of an auto-configuration
* class to enable the agent as soon as possible during the startup process.
*
* @author Brian Clozel
* @since 2.2.0
*/
public class DebugAgentEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
调试代理???先看看postProcessEnvironment方法:
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
if (ClassUtils.isPresent(REACTOR_DEBUGAGENT_CLASS, null)) {
Boolean agentEnabled = environment.getProperty(DEBUGAGENT_ENABLED_CONFIG_KEY, Boolean.class);
if (agentEnabled != Boolean.FALSE) {
try {
Class<?> debugAgent = Class.forName(REACTOR_DEBUGAGENT_CLASS);
debugAgent.getMethod("init").invoke(null);
}
catch (Exception ex) {
throw new RuntimeException("Failed to init Reactor's debug agent");
}
}
}
}
这里貌似涉及到其他领域了,Reactor?这个先留个钩子,后面再来补。
至此,所有的环境处理器执行完成。