共计 27295 个字符,预计需要花费 69 分钟才能阅读完成。
Spring 源码解析十三:SpringBoot 初始化利用时加载的组件
这些组件定义在 spring.factories
中
# 日志零碎
org.springframework.boot.logging.LoggingSystemFactory=\
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
org.springframework.boot.logging.java.JavaLoggingSystem.Factory
# 属性起源加载器
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
# 配置数据起源解析器
org.springframework.boot.context.config.ConfigDataLocationResolver=\
org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
org.springframework.boot.context.config.StandardConfigDataLocationResolver
# 配置数据加载器
org.springframework.boot.context.config.ConfigDataLoader=\
org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
org.springframework.boot.context.config.StandardConfigDataLoader
# 利用运行监听器
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
# 错误报告器
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
# 利用上下文初始加载器
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
# 利用监听器
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
# 环境后置处理器
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
# 失败分析器
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer,\
org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer,\
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer,\
org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer
# 失败剖析报告器
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
1. 日志零碎
org.springframework.boot.logging.LoggingSystemFactory=\
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
org.springframework.boot.logging.java.JavaLoggingSystem.Factory
配置中阐明 SpringBoot 内置反对 logback
、logback
、java
原生三种日志解决,具体源代码能够自行摸索
- LogbackLoggingSystem
- Log4J2LoggingSystem
- JavaLoggingSystem
2. 属性起源加载器
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
配置中阐明 SpringBoot 内置反对 application*.properties
、application*.yaml
两种文件格式加载属性配置起源,具体源代码能够自行摸索
- PropertiesPropertySourceLoader
- YamlPropertySourceLoader
3. 配置数据起源解析器 & 配置数据加载器
# 配置数据起源解析器
org.springframework.boot.context.config.ConfigDataLocationResolver=\
org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
org.springframework.boot.context.config.StandardConfigDataLocationResolver
# 配置数据加载器
org.springframework.boot.context.config.ConfigDataLoader=\
org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
org.springframework.boot.context.config.StandardConfigDataLoader
这一组放在一起解析,是因为他们一起实现了一个性能:
- ConfigDataLocationResolver
将spring.config.import
、spring.config.addtional-location
、spring.config.location
等资源定位门路下的application*.[properties/yaml]
资源解析成 ConfigDataResource
资源对象,期待加载 - ConfigDataLoader
将解析好的资源对象进行加载,把ConfigDataResource
转换成 ConfigData
(ConfigData
是一组PropertySource
) - 将加载好的
ConfigData
增加到上下文对象中
ConfigTreeConfigDataLocationResolver
与 ConfigTreeConfigDataLoader
次要是读取 Kubernetes Volume 的 configMap 配置,这里就不做解析了
3.1. StandardConfigDataLocationResolver
StandardConfigDataLocationResolver
的次要性能是解析内部配置文件
public class StandardConfigDataLocationResolver
implements ConfigDataLocationResolver<StandardConfigDataResource>, Ordered {public StandardConfigDataLocationResolver(Log logger, Binder binder, ResourceLoader resourceLoader) {
// 加载 `spring.factories` 中的属性加载器,properties+yaml
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
getClass().getClassLoader());
// 获取 `spring.config.name` 指定的利用名称,默认是 `application`
this.configNames = getConfigNames(binder);
// ... 代码省略
}
// 解析门路 location
@Override
public List<StandardConfigDataResource> resolve(ConfigDataLocationResolverContext context,
ConfigDataLocation location) throws ConfigDataNotFoundException {
// 获取数据援用,而后解析
return resolve(getReferences(context, location));
}
// 获取数据援用
private Set<StandardConfigDataReference> getReferences(ConfigDataLocationResolverContext context,
ConfigDataLocation configDataLocation) {
// 获取资源地位
String resourceLocation = getResourceLocation(context, configDataLocation);
try {
// 如果是目录,就按目录加载
if (isDirectory(resourceLocation)) {// 加载目录下所有的 application*.[properties/yaml] 文件配置
return getReferencesForDirectory(configDataLocation, resourceLocation, NO_PROFILE);
}
// 不然就按文件加载,获取指定文件的援用
return getReferencesForFile(configDataLocation, resourceLocation, NO_PROFILE);
}
catch (RuntimeException ex) {// ... 代码省略}
}
// 解析门路 location 中指定 profile 的文件
@Override
public List<StandardConfigDataResource> resolveProfileSpecific(ConfigDataLocationResolverContext context,
ConfigDataLocation location, Profiles profiles) {
// 获取数据援用,而后解析
return resolve(getProfileSpecificReferences(context, location, profiles));
}
// 获取指定 profile 的数据援用
private Set<StandardConfigDataReference> getProfileSpecificReferences(ConfigDataLocationResolverContext context,
ConfigDataLocation configDataLocation, Profiles profiles) {Set<StandardConfigDataReference> references = new LinkedHashSet<>();
// 获取资源地位
String resourceLocation = getResourceLocation(context, configDataLocation);
// 遍历 profiles 加载
for (String profile : profiles) {references.addAll(getReferences(configDataLocation, resourceLocation, profile));
}
return references;
}
}
public class StandardConfigDataLocationResolver
implements ConfigDataLocationResolver<StandardConfigDataResource>, Ordered {
// 获取资源地位
private String getResourceLocation(ConfigDataLocationResolverContext context,
ConfigDataLocation configDataLocation) {
// 去掉 "resource:" 前缀
String resourceLocation = configDataLocation.getNonPrefixedValue(PREFIX);
// 如果是以 / 结尾或者是 [protocol]: 结尾的,就算是绝对路径,间接返回
boolean isAbsolute = resourceLocation.startsWith("/") || URL_PREFIX.matcher(resourceLocation).matches();
if (isAbsolute) {return resourceLocation;}
// 否则以相对路径看待,加载父门路前缀再返回
ConfigDataResource parent = context.getParent();
if (parent instanceof StandardConfigDataResource) {String parentResourceLocation = ((StandardConfigDataResource) parent).getReference().getResourceLocation();
String parentDirectory = parentResourceLocation.substring(0, parentResourceLocation.lastIndexOf("/") + 1);
return parentDirectory + resourceLocation;
}
return resourceLocation;
}
// 解析 StandardConfigDataReference 为 StandardConfigDataResource
private List<StandardConfigDataResource> resolve(Set<StandardConfigDataReference> references) {List<StandardConfigDataResource> resolved = new ArrayList<>();
for (StandardConfigDataReference reference : references) {resolved.addAll(resolve(reference));
}
if (resolved.isEmpty()) {resolved.addAll(resolveEmptyDirectories(references));
}
return resolved;
}
}
3.2. StandardConfigDataLoader
StandardConfigDataLoader
的次要性能是读取内部配置文件里的值
public class StandardConfigDataLoader implements ConfigDataLoader<StandardConfigDataResource> {
// 加载文件为 ConfigData
@Override
public ConfigData load(ConfigDataLoaderContext context, StandardConfigDataResource resource)
throws IOException, ConfigDataNotFoundException {
// ... 代码省略
StandardConfigDataReference reference = resource.getReference();
Resource originTrackedResource = OriginTrackedResource.of(resource.getResource(),
Origin.from(reference.getConfigDataLocation()));
String name = String.format("Config resource'%s'via location'%s'", resource,
reference.getConfigDataLocation());
// 读取为 propertySources
List<PropertySource<?>> propertySources = reference.getPropertySourceLoader().load(name, originTrackedResource);
return new ConfigData(propertySources);
}
}
4. 利用运行监听器
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
EventPublishingRunListener
的次要性能是公布利用事件,调用事件监听函数
5. 错误报告器
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
FailureAnalyzers
的次要性能是向用户报告程序谬误
6. 利用上下文初始加载器
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
- ConfigurationWarningsApplicationContextInitializer
配置谬误正告 - ContextIdApplicationContextInitializer
配置 ContextId - DelegatingApplicationContextInitializer
初始化context.initializer.classes
配置的类 - RSocketPortInfoApplicationContextInitializer
初始化local.rsocket.server.port
配置信息 - ServerPortInfoApplicationContextInitializer
初始化server.port
配置信息
这些类都比较简单,以 ConfigurationWarningsApplicationContextInitializer
为例解析
public class ConfigurationWarningsApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
// 初始化组件
@Override
public void initialize(ConfigurableApplicationContext context) {context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
}
protected static final class ConfigurationWarningsPostProcessor
implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {
// bean 定义后置解决
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {for (Check check : this.checks) {
// 如果 @ComponentScan 扫描了 org.springframework 或 org,则正告谬误
String message = check.getWarning(registry);
if (StringUtils.hasLength(message)) {warn(message);
}
}
}
}
}
7. 利用监听器
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
- ClearCachesApplicationListener
革除缓存 - ParentContextCloserApplicationListener
父上下文敞开 - FileEncodingApplicationListener
文件编码有误 - AnsiOutputApplicationListener
Ansi 输入 - DelegatingApplicationListener
代理context.listener.classes
配置的监听器 - LoggingApplicationListener
利用日志 - EnvironmentPostProcessorApplicationListener
触发 EnvironmentPostProcessor
组件
这些类都比较简单,能够自行摸索
8. 环境后置处理器
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
8.1. CloudFoundryVcapEnvironmentPostProcessor
CloudFoundryVcapEnvironmentPostProcessor
的次要性能是反对 CloudFoundry(一个开源 PaaS 云平台)
8.2. ConfigDataEnvironmentPostProcessor
ConfigDataEnvironmentPostProcessor
的次要性能是加载和利用 ConfigData
到 Spring 环境中
public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
}
void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
Collection<String> additionalProfiles) {
try {
// 获取资源加载器
resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
// 加载和利用
getConfigDataEnvironment(environment, resourceLoader, additionalProfiles).processAndApply();}
catch (UseLegacyConfigProcessingException ex) {// ... 代码省略}
}
// 获取环境对象
ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
Collection<String> additionalProfiles) {
return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader,
additionalProfiles, this.environmentUpdateListener);
}
}
理论加载与利用是由 ConfigDataEnvironment
实现的
class ConfigDataEnvironment {
// 用于笼罩默认属性加载的中央
static final String LOCATION_PROPERTY = "spring.config.location";
// 默认之外,其余属性加载的中央
static final String ADDITIONAL_LOCATION_PROPERTY = "spring.config.additional-location";
// 导入第三方属性文件
static final String IMPORT_PROPERTY = "spring.config.import";
// 默认属性加载的中央
// 1. 加载 classpath:/application*.yaml
// 2. 加载 classpath:/config/application*.yaml
// 3. 加载 file:./application*.yaml
// 4. 加载 file:./config/application*.yaml
// 5. 加载 file:./config/*/application*.yaml
static final ConfigDataLocation[] DEFAULT_SEARCH_LOCATIONS;
static {List<ConfigDataLocation> locations = new ArrayList<>();
locations.add(ConfigDataLocation.of("optional:classpath:/"));
locations.add(ConfigDataLocation.of("optional:classpath:/config/"));
locations.add(ConfigDataLocation.of("optional:file:./"));
locations.add(ConfigDataLocation.of("optional:file:./config/"));
locations.add(ConfigDataLocation.of("optional:file:./config/*/"));
DEFAULT_SEARCH_LOCATIONS = locations.toArray(new ConfigDataLocation[0]);
}
// 属性值提供器
private final ConfigDataEnvironmentContributors contributors;
ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
// ... 代码省略
// 创立默认的属性值提供器
this.contributors = createContributors(binder);
}
// 创立默认的属性值提供器
private ConfigDataEnvironmentContributors createContributors(Binder binder) {
// 获取属性值起源
MutablePropertySources propertySources = this.environment.getPropertySources();
// 后果集
List<ConfigDataEnvironmentContributor> contributors = new ArrayList<>(propertySources.size() + 10);
// 默认的属性值起源
PropertySource<?> defaultPropertySource = null;
for (PropertySource<?> propertySource : propertySources) {
// default properties
if (DefaultPropertiesPropertySource.hasMatchingName(propertySource)) {defaultPropertySource = propertySource;}
// 其余的
else {contributors.add(ConfigDataEnvironmentContributor.ofExisting(propertySource));
}
}
// 获取默认的提供器
contributors.addAll(getInitialImportContributors(binder));
// 如果有默认的,增加到最初面
if (defaultPropertySource != null) {contributors.add(ConfigDataEnvironmentContributor.ofExisting(defaultPropertySource));
}
// 创立 ConfigDataEnvironmentContributors
return createContributors(contributors);
}
// 获取默认的提供器
private List<ConfigDataEnvironmentContributor> getInitialImportContributors(Binder binder) {
// 后果集
List<ConfigDataEnvironmentContributor> initialContributors = new ArrayList<>();
// 增加 `spring.config.import` 指定的资源
addInitialImportContributors(initialContributors, bindLocations(binder, IMPORT_PROPERTY, EMPTY_LOCATIONS));
// 增加 `spring.config.additional-location` 指定的资源
addInitialImportContributors(initialContributors,
bindLocations(binder, ADDITIONAL_LOCATION_PROPERTY, EMPTY_LOCATIONS));
// 增加 `spring.config.location` 指定的资源
//(会笼罩默认属性加载的中央:classpath:/, classpath:/config/, file:./, file:./config/, file:./config/*/)addInitialImportContributors(initialContributors,
bindLocations(binder, LOCATION_PROPERTY, DEFAULT_SEARCH_LOCATIONS));
return initialContributors;
}
}
class ConfigDataEnvironment {
// 解决及利用
void processAndApply() {
// 创立 ConfigDataImporter
ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, this.notFoundAction, this.resolvers,
this.loaders);
// 绑定 contributors
registerBootstrapBinder(this.contributors, null, DENY_INACTIVE_BINDING);
// 导入 `spring.config.import` 指定的资源,从新绑定 contributors
ConfigDataEnvironmentContributors contributors = processInitial(this.contributors, importer);
// 创立一个配置数据激活上下文对象,如果绑定到了没有 active 的属性源,则报错
// 比方:spring.profiles.active=prod,但绑定了 application-dev.yaml
ConfigDataActivationContext activationContext = createActivationContext(contributors.getBinder(null, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
// 导入无 profile `application.yaml` 的资源,从新绑定 contributors
contributors = processWithoutProfiles(contributors, importer, activationContext);
// 载入 profiles 到绑定的上下文中
activationContext = withProfiles(contributors, activationContext);
// 导入激活 profile `application-[active].yaml` 的资源,从新绑定 contributors
contributors = processWithProfiles(contributors, importer, activationContext);
// 利用到环境中
applyToEnvironment(contributors, activationContext);
}
// 导入 `spring.config.import` 指定的资源,从新绑定 contributors
private ConfigDataEnvironmentContributors processInitial(ConfigDataEnvironmentContributors contributors,
ConfigDataImporter importer) {contributors = contributors.withProcessedImports(importer, null);
registerBootstrapBinder(contributors, null, DENY_INACTIVE_BINDING);
return contributors;
}
// 导入无 profile `application.yaml` 的资源,从新绑定 contributors
private ConfigDataEnvironmentContributors processWithoutProfiles(ConfigDataEnvironmentContributors contributors,
ConfigDataImporter importer, ConfigDataActivationContext activationContext) {contributors = contributors.withProcessedImports(importer, activationContext);
registerBootstrapBinder(contributors, activationContext, DENY_INACTIVE_BINDING);
return contributors;
}
// 载入 profiles 到绑定的上下文中
private ConfigDataActivationContext withProfiles(ConfigDataEnvironmentContributors contributors,
ConfigDataActivationContext activationContext) {
// 获取绑定对象
Binder binder = contributors.getBinder(activationContext,
ConfigDataEnvironmentContributor::isNotIgnoringProfiles, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
try {
// 参数输出的 profiles
Set<String> additionalProfiles = new LinkedHashSet<>(this.additionalProfiles);
// 载入以后激活环境中 `spring.profiles.include` 指定的其余环境
additionalProfiles.addAll(getIncludedProfiles(contributors, activationContext));
// 创立 Profiles 对象,载入到上下文中
Profiles profiles = new Profiles(this.environment, binder, additionalProfiles);
return activationContext.withProfiles(profiles);
}
catch (BindException ex) {// ... 代码省略}
}
// 导入激活 profile `application-[active].yaml` 的资源,从新绑定 contributors
private ConfigDataEnvironmentContributors processWithProfiles(ConfigDataEnvironmentContributors contributors,
ConfigDataImporter importer, ConfigDataActivationContext activationContext) {contributors = contributors.withProcessedImports(importer, activationContext);
registerBootstrapBinder(contributors, activationContext, ALLOW_INACTIVE_BINDING);
return contributors;
}
// 利用到环境中
private void applyToEnvironment(ConfigDataEnvironmentContributors contributors,
ConfigDataActivationContext activationContext) {
// ... 代码省略
// 属性起源
MutablePropertySources propertySources = this.environment.getPropertySources();
// 遍历 contributors
for (ConfigDataEnvironmentContributor contributor : contributors) {PropertySource<?> propertySource = contributor.getPropertySource();
// ... 代码省略
// 如果是激活的,退出到环境的 propertySources 中
if (contributor.isActive(activationContext)) {propertySources.addLast(propertySource);
}
}
// ... 代码省略
}
}
理论资源载入是由 ConfigDataEnvironmentContributors
实现的
class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmentContributor> {
// 解决载入属性值
ConfigDataEnvironmentContributors withProcessedImports(ConfigDataImporter importer,
ConfigDataActivationContext activationContext) {
// 每次载入新的文件后,都返回一个新的对象
ConfigDataEnvironmentContributors result = this;
int processed = 0;
while (true) {
// 获取下一个能够载入的文件
ConfigDataEnvironmentContributor contributor = getNextToProcess(result, activationContext, importPhase);
// 没有下一个了,返回
if (contributor == null) {return result;}
// 非导入其余文件
if (contributor.getKind() == Kind.UNBOUND_IMPORT) {
// 配置属性源
Iterable<ConfigurationPropertySource> sources = Collections
.singleton(contributor.getConfigurationPropertySource());
// 占位符解析器
PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(result, activationContext, true);
// 新建绑定
Binder binder = new Binder(sources, placeholdersResolver, null, null, null);
// 生成一个新的 ConfigDataEnvironmentContributor
ConfigDataEnvironmentContributor bound = contributor.withBoundProperties(binder);
// 生成一个新的对象
result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapContext,
result.getRoot().withReplacement(contributor, bound));
continue;
}
// 门路解析上下文
ConfigDataLocationResolverContext locationResolverContext = new ContributorConfigDataLocationResolverContext(result, contributor, activationContext);
// 加载上下文
ConfigDataLoaderContext loaderContext = new ContributorDataLoaderContext(this);
// 获取导入的资源门路
List<ConfigDataLocation> imports = contributor.getImports();
// 导入资源为 ConfigData
Map<ConfigDataResolutionResult, ConfigData> imported = importer.resolveAndLoad(activationContext,
locationResolverContext, loaderContext, imports);
// 合并以后与上一次的属性值
ConfigDataEnvironmentContributor contributorAndChildren = contributor.withChildren(importPhase,
asContributors(imported));
// 生成一个新的对象
result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapContext,
result.getRoot().withReplacement(contributor, contributorAndChildren));
processed++;
}
}
}
8.3. CloudFoundryVcapEnvironmentPostProcessor
CloudFoundryVcapEnvironmentPostProcessor
的次要性能是反对以 random.
结尾的属性配置转换成理论的随机值
8.4. SpringApplicationJsonEnvironmentPostProcessor
SpringApplicationJsonEnvironmentPostProcessor
的次要性能是反对用 spring.application.json
参数或 SPRING_APPLICATION_JSON
环境变量作为初始化参数传入 JSON 数据
public class SpringApplicationJsonEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
// 获取属性起源
MutablePropertySources propertySources = environment.getPropertySources();
// 流式解决 `spring.application.json` 参数或 `SPRING_APPLICATION_JSON` 环境变量
propertySources.stream().map(JsonPropertyValue::get).filter(Objects::nonNull).findFirst()
.ifPresent((v) -> processJson(environment, v));
}
private void processJson(ConfigurableEnvironment environment, JsonPropertyValue propertyValue) {
// 获取 JSON 解析器
JsonParser parser = JsonParserFactory.getJsonParser();
// 解析成 Map
Map<String, Object> map = parser.parseMap(propertyValue.getJson());
// 有值
if (!map.isEmpty()) {
// 增加为一个 JSON 起源
addJsonPropertySource(environment, new JsonPropertySource(propertyValue, flatten(map)));
}
}
}
public abstract class JsonParserFactory {public static JsonParser getJsonParser() {
// 默认首先应用 Jackson
if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {return new JacksonJsonParser();
}
// 其次应用 Gson
if (ClassUtils.isPresent("com.google.gson.Gson", null)) {return new GsonJsonParser();
}
// 其次应用 Yaml
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {return new YamlJsonParser();
}
// 都没有,应用内置的
return new BasicJsonParser();}
}
8.5. SystemEnvironmentPropertySourceEnvironmentPostProcessor
SystemEnvironmentPropertySourceEnvironmentPostProcessor
的次要性能是解决 systemEnvironment
属性起源
8.6. DebugAgentEnvironmentPostProcessor
DebugAgentEnvironmentPostProcessor
的次要性能是解决 spring.reactor.debug-agent.enabled
9. 失败分析器
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer,\
org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer,\
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer,\
org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer
- ConfigDataNotFoundFailureAnalyzer
无ConfigData
- IncompatibleConfigurationFailureAnalyzer
不兼容的配置 - NotConstructorBoundInjectionFailureAnalyzer
没有绑定注入 bean 的实例化 - BeanCurrentlyInCreationFailureAnalyzer
bean 正在创立 - BeanDefinitionOverrideFailureAnalyzer
bean 定义被笼罩重写 - BeanNotOfRequiredTypeFailureAnalyzer
bean 不是指定类型 - BindFailureAnalyzer
绑定属性值失败 - BindValidationFailureAnalyzer
绑定验证失败 - UnboundConfigurationPropertyFailureAnalyzer
更新解绑配置失败 - ConnectorStartFailureAnalyzer
tomcat 链接失败 - NoSuchMethodFailureAnalyzer
没有办法 - NoUniqueBeanDefinitionFailureAnalyzer
不是惟一的 bean 定义 - PortInUseFailureAnalyzer
端口已被占用 - ValidationExceptionFailureAnalyzer
数据验证失败 - InvalidConfigurationPropertyNameFailureAnalyzer
不非法配置属性名 - InvalidConfigurationPropertyValueFailureAnalyzer
不非法配置属性值 - PatternParseFailureAnalyzer
正则解析失败 - LiquibaseChangelogMissingFailureAnalyzer
Liquibase changelog 不存在
这些类都比较简单,能够自行摸索
10. 失败剖析报告器
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
LoggingFailureAnalysisReporter
的次要性能是利用启动失败,报告起因 APPLICATION FAILED TO START
后续
更多博客,查看 https://github.com/senntyou/blogs
作者:深予之 (@senntyou)
版权申明:自在转载 - 非商用 - 非衍生 - 放弃署名(创意共享 3.0 许可证)