后处理器是在监听器EnvironmentPostProcessorApplicationListener
中被加载。
入口在SpringApplication
实例方法prepareEnvironment
,第343行。
listeners.environmentPrepared(bootstrapContext, environment);
这里触发了事件ApplicationEnvironmentPreparedEvent
相关监听器
监听器 | Order |
---|---|
DelegatingApplicationListener | 0 |
EnvironmentPostProcessorApplicationListener | Integer.MIN_VALUE + 10 |
LoggingApplicationListener | Integer.MIN_VALUE + 20 |
AnsiOutputApplicationListener | Integer.MIN_VALUE + 11 |
FileEncodingApplicationListener | Integer.MAX_VALUE |
排序后,触发顺序
DelegatingApplicationListener
EnvironmentPostProcessorApplicationListener
AnsiOutputApplicationListener
LoggingApplicationListener
FileEncodingApplicationListener
EnvironmentPostProcessorApplicationListener
就是监听器之一。
EnvironmentPostProcessorApplicationListener
主要方法
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
SpringApplication application = event.getSpringApplication();
for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),
event.getBootstrapContext())) {
postProcessor.postProcessEnvironment(environment, application);
}
}
List<EnvironmentPostProcessor> getEnvironmentPostProcessors(ResourceLoader resourceLoader,
ConfigurableBootstrapContext bootstrapContext) {
ClassLoader classLoader = (resourceLoader != null) ? resourceLoader.getClassLoader() : null;
EnvironmentPostProcessorsFactory postProcessorsFactory = this.postProcessorsFactory.apply(classLoader);
return postProcessorsFactory.getEnvironmentPostProcessors(this.deferredLogs, bootstrapContext);
}
其中this.postProcessorsFactory
是EnvironmentPostProcessorsFactory::fromSpringFactories
static EnvironmentPostProcessorsFactory fromSpringFactories(ClassLoader classLoader) {
return new ReflectionEnvironmentPostProcessorsFactory(classLoader,
SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));
}
EnvironmentPostProcessor
的实现类
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.autoconfigure.integration.IntegrationPropertiesEnvironmentPostProcessor
处理器 | Order值 |
---|---|
CloudFoundryVcapEnvironmentPostProcessor | Integer.MIN_VALUE + 10 - 1 |
ConfigDataEnvironmentPostProcessor | Integer.MIN_VALUE + 10 |
RandomValuePropertySourceEnvironmentPostProcessor | Integer.MIN_VALUE + 1 |
SpringApplicationJsonEnvironmentPostProcessor | Integer.MIN_VALUE + 5 |
SystemEnvironmentPropertySourceEnvironmentPostProcessor | Integer.MIN_VALUE + 5 - 1 |
DebugAgentEnvironmentPostProcessor | Integer.MAX_VALUE |
IntegrationPropertiesEnvironmentPostProcessor | Integer.MAX_VALUE |
最后顺序
RandomValuePropertySourceEnvironmentPostProcessor
SystemEnvironmentPropertySourceEnvironmentPostProcessor
SpringApplicationJsonEnvironmentPostProcessor
CloudFoundryVcapEnvironmentPostProcessor
ConfigDataEnvironmentPostProcessor
DebugAgentEnvironmentPostProcessor
IntegrationPropertiesEnvironmentPostProcessor
EnvironmentPostProcessorApplicationListener
实例化的时候,是调用的无参构造方法。
public EnvironmentPostProcessorApplicationListener() {
this(EnvironmentPostProcessorsFactory::fromSpringFactories, new DeferredLogs());
}
实例化后关键属性
属性 | 值 |
---|---|
postProcessorsFactory | EnvironmentPostProcessorsFactory::fromSpringFactories |
deferredLogs | DeferredLogFactory |
ReflectionEnvironmentPostProcessorsFactory
实例化后的属性
属性 | 值 |
---|---|
classes | null |
classLoader | null |
classNames | EnvironmentPostProcessor实现类的类全限定名\ |
加载EnvironmentPostProcessor
实现类的主要逻辑
@Override
public List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext) {
Instantiator<EnvironmentPostProcessor> instantiator = new Instantiator<>(EnvironmentPostProcessor.class,
(parameters) -> {
parameters.add(DeferredLogFactory.class, logFactory);
parameters.add(Log.class, logFactory::getLog);
parameters.add(ConfigurableBootstrapContext.class, bootstrapContext);
parameters.add(BootstrapContext.class, bootstrapContext);
parameters.add(BootstrapRegistry.class, bootstrapContext);
});
return (this.classes != null) ? instantiator.instantiateTypes(this.classes)
: instantiator.instantiate(this.classLoader, this.classNames);
}
public Instantiator(Class<?> type, Consumer<AvailableParameters> availableParameters) {
this(type, availableParameters, throwingFailureHandler);
}
public Instantiator(Class<?> type, Consumer<AvailableParameters> availableParameters,
FailureHandler failureHandler) {
this.type = type;
this.availableParameters = getAvailableParameters(availableParameters);
this.failureHandler = failureHandler;
}
Instantiator
是一个通过用的实例化工具类。
主要逻辑:
- 获取要实例化的类的构造方法,按照构造方法的参数个数倒序排序。
- 然后检查每个参数,是否是给定参数集合中类的子类或者类本身。
- 如果找到了,就把给定参数集合中的值作为参数返回,拿去调用构造方法
- 优先使用个数多个的构造方法,默认使用无参构造
- 构造完成后,使用
AnnotationAwareOrderComparator
比较器排序一番。
属性 | 值 |
---|---|
type | EnvironmentPostProcessor.class |
availableParameters | DeferredLogFactory.class factoryType -> DeferredLogs |
Log.class | logFactory::getLog |
ConfigurableBootstrapContext.class | factoryType -> bootstrapContext |
BootstrapContext.class | factoryType -> bootstrapContext |
BootstrapRegistry.class | factoryType -> bootstrapContext |
failureHandler | 初始化失败后的处理器,默认是抛异常 |
RandomValuePropertySourceEnvironmentPostProcessor
构造方法
public RandomValuePropertySourceEnvironmentPostProcessor(Log logger) {
this.logger = logger;
}
SystemEnvironmentPropertySourceEnvironmentPostProcessor
默认无参构造
SpringApplicationJsonEnvironmentPostProcessor
默认无参构造
CloudFoundryVcapEnvironmentPostProcessor
构造方法
public CloudFoundryVcapEnvironmentPostProcessor(Log logger) {
this.logger = logger;
}
ConfigDataEnvironmentPostProcessor
构造方法
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext) {
this(logFactory, bootstrapContext, null);
}
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
this.logFactory = logFactory;
this.logger = logFactory.getLog(getClass());
this.bootstrapContext = bootstrapContext;
this.environmentUpdateListener = environmentUpdateListener;
}
DebugAgentEnvironmentPostProcessor
默认无参构造
IntegrationPropertiesEnvironmentPostProcessor
默认无参构造
最后得到各自的构造方法
类 | 构造方法 |
---|---|
RandomValuePropertySourceEnvironmentPostProcessor | public RandomValuePropertySourceEnvironmentPostProcessor(Log logger) |
SystemEnvironmentPropertySourceEnvironmentPostProcessor | 无参构造 |
SpringApplicationJsonEnvironmentPostProcessor | 无参构造 |
CloudFoundryVcapEnvironmentPostProcessor | public CloudFoundryVcapEnvironmentPostProcessor(Log logger) |
ConfigDataEnvironmentPostProcessor | public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactoryConfigurableBootstrapContext bootstrapContext) |
DebugAgentEnvironmentPostProcessor | 无参构造 |
IntegrationPropertiesEnvironmentPostProcessor | 无参构造 |
实例化后排序 |
RandomValuePropertySourceEnvironmentPostProcessor
SystemEnvironmentPropertySourceEnvironmentPostProcessor
SpringApplicationJsonEnvironmentPostProcessor
CloudFoundryVcapEnvironmentPostProcessor
ConfigDataEnvironmentPostProcessor
DebugAgentEnvironmentPostProcessor
IntegrationPropertiesEnvironmentPostProcessor
逻辑
RandomValuePropertySourceEnvironmentPostProcessor
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
RandomValuePropertySource.addToEnvironment(environment, this.logger);
}
这个处理器会创建一个Random
对象,放入sources
,key
为random
如果环境变量已经加载,就放在环境变量后面,没有加载,就放到最后
SystemEnvironmentPropertySourceEnvironmentPostProcessor
@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, application.getEnvironmentPrefix());
}
}
@SuppressWarnings("unchecked")
private void replacePropertySource(ConfigurableEnvironment environment, String sourceName,
PropertySource<?> propertySource, String environmentPrefix) {
Map<String, Object> originalSource = (Map<String, Object>) propertySource.getSource();
SystemEnvironmentPropertySource source = new OriginAwareSystemEnvironmentPropertySource(sourceName,
originalSource, environmentPrefix);
environment.getPropertySources().replace(sourceName, source);
}
这个处理器会处理系统环境变量,把系统环境变量包装成OriginAwareSystemEnvironmentPropertySource
SpringApplicationJsonEnvironmentPostProcessor
@Override
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));
}
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)));
}
}
public static JsonParser getJsonParser() {
if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
return new JacksonJsonParser();
}
if (ClassUtils.isPresent("com.google.gson.Gson", null)) {
return new GsonJsonParser();
}
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
return new YamlJsonParser();
}
return new BasicJsonParser();
}
这个处理器会从环境变量中获取spring.application.json
或者SPRING_APPLICATION_JSON
的配置,然后找到第一个配置,使用json解析器解析,放入source
,名称为spring.application.json
,位置在servletContextInitParams
或者servletConfigInitParams
之前。
CloudFoundryVcapEnvironmentPostProcessor
@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));
}
}
}
这个处理器,会从环境变量获取spring.main.cloud-platform
的值,如果是CloudPlatform.CLOUD_FOUNDRY
类型,如果值是CLOUD_FOUNDRY
或者包含VCAP_APPLICATION
或VCAP_SERVICES
,就执行开源云平台的逻辑。
从环境变量中获取VCAP_APPLICATION
和VCAP_SERVICES
的值,用json解析器解析,分别加上前缀vcap.application.
和vcap.services.
,放入sources
,名称是vcap
,位置上,如果有命令行参数,就放在命令行参数后面,如果没有,就放首位。
ConfigDataEnvironmentPostProcessor
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
}
ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
Collection<String> additionalProfiles) {
return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader,
additionalProfiles, this.environmentUpdateListener);
}
创建一个ConfigDataEnvironment
实例,过程中会创建一个ConfigDataLocationResolvers
实例。
ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
Binder binder = Binder.get(environment);
UseLegacyConfigProcessingException.throwIfRequested(binder);
this.logFactory = logFactory;
this.logger = logFactory.getLog(getClass());
this.notFoundAction = binder.bind(ON_NOT_FOUND_PROPERTY, ConfigDataNotFoundAction.class)
.orElse(ConfigDataNotFoundAction.FAIL);
this.bootstrapContext = bootstrapContext;
this.environment = environment;
this.resolvers = createConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader);
this.additionalProfiles = additionalProfiles;
this.environmentUpdateListener = (environmentUpdateListener != null) ? environmentUpdateListener
: ConfigDataEnvironmentUpdateListener.NONE;
this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext, resourceLoader.getClassLoader());
this.contributors = createContributors(binder);
}
感觉像是捅了马蜂窝了。
ConfigDataLocationResolvers
实例化,会加载ConfigDataLocationResolver
的实现类。
# ConfigData Location Resolvers
org.springframework.boot.context.config.ConfigDataLocationResolver=\
org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
org.springframework.boot.context.config.StandardConfigDataLocationResolver
ConfigTreeConfigDataLocationResolver
实例化,会创建LocationResourceLoader
实例
StandardConfigDataLocationResolver
实例化,会加载PropertySourceLoader
的实现类
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
StandardConfigDataLocationResolver
中会设置应用的配置文件名称,key是spring.config.name
,默认值是application
,也就是Spring
配置文件的名字也是可以配置的,这个名字中不能包含*号。
至于PropertiesPropertySourceLoader
和YamlPropertySourceLoader
,就是解析Spring
配置文件的两个加载器,前者解析properties
后缀文件,后者解析yml
后缀文件。
ConfigDataLocationResolvers
中,在加载完成ConfigDataLocationResolver
的接口后,会重新排序,把StandardConfigDataLocationResolver
的子类或本身保留最后实现,放入集合末尾。
ConfigDataEnvironment
实例化时,会创建ConfigDataLoaders
实例,进而加载ConfigDataLoader
的实例。
# ConfigData Loaders
org.springframework.boot.context.config.ConfigDataLoader=\
org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
org.springframework.boot.context.config.StandardConfigDataLoader
然后调用processAndApply
,会读取配置文件。
void processAndApply() {
ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, this.notFoundAction, this.resolvers,
this.loaders);
registerBootstrapBinder(this.contributors, null, DENY_INACTIVE_BINDING);
ConfigDataEnvironmentContributors contributors = processInitial(this.contributors, importer);
ConfigDataActivationContext activationContext = createActivationContext(
contributors.getBinder(null, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
contributors = processWithoutProfiles(contributors, importer, activationContext);
activationContext = withProfiles(contributors, activationContext);
contributors = processWithProfiles(contributors, importer, activationContext);
applyToEnvironment(contributors, activationContext, importer.getLoadedLocations(),
importer.getOptionalLocations());
}
private ConfigDataEnvironmentContributors processInitial(ConfigDataEnvironmentContributors contributors,
ConfigDataImporter importer) {
this.logger.trace("Processing initial config data environment contributors without activation context");
contributors = contributors.withProcessedImports(importer, null);
registerBootstrapBinder(contributors, null, DENY_INACTIVE_BINDING);
return contributors;
}