Spring 源码解析十三:SpringBoot 初始化应用时加载的组件

x33g5p2x  于2022-02-11 发布在 Spring  
字(27.6k)|赞(0)|评价(0)|浏览(576)

这些组件定义在 spring.factories

  1. # 日志系统
  2. org.springframework.boot.logging.LoggingSystemFactory=\
  3. org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
  4. org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
  5. org.springframework.boot.logging.java.JavaLoggingSystem.Factory
  6. # 属性来源加载器
  7. org.springframework.boot.env.PropertySourceLoader=\
  8. org.springframework.boot.env.PropertiesPropertySourceLoader,\
  9. org.springframework.boot.env.YamlPropertySourceLoader
  10. # 配置数据来源解析器
  11. org.springframework.boot.context.config.ConfigDataLocationResolver=\
  12. org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
  13. org.springframework.boot.context.config.StandardConfigDataLocationResolver
  14. # 配置数据加载器
  15. org.springframework.boot.context.config.ConfigDataLoader=\
  16. org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
  17. org.springframework.boot.context.config.StandardConfigDataLoader
  18. # 应用运行监听器
  19. org.springframework.boot.SpringApplicationRunListener=\
  20. org.springframework.boot.context.event.EventPublishingRunListener
  21. # 错误报告器
  22. org.springframework.boot.SpringBootExceptionReporter=\
  23. org.springframework.boot.diagnostics.FailureAnalyzers
  24. # 应用上下文初始加载器
  25. org.springframework.context.ApplicationContextInitializer=\
  26. org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
  27. org.springframework.boot.context.ContextIdApplicationContextInitializer,\
  28. org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
  29. org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
  30. org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
  31. # 应用监听器
  32. org.springframework.context.ApplicationListener=\
  33. org.springframework.boot.ClearCachesApplicationListener,\
  34. org.springframework.boot.builder.ParentContextCloserApplicationListener,\
  35. org.springframework.boot.context.FileEncodingApplicationListener,\
  36. org.springframework.boot.context.config.AnsiOutputApplicationListener,\
  37. org.springframework.boot.context.config.DelegatingApplicationListener,\
  38. org.springframework.boot.context.logging.LoggingApplicationListener,\
  39. org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
  40. # 环境后置处理器
  41. org.springframework.boot.env.EnvironmentPostProcessor=\
  42. org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
  43. org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
  44. org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
  45. org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
  46. org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
  47. org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
  48. # 失败分析器
  49. org.springframework.boot.diagnostics.FailureAnalyzer=\
  50. org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer,\
  51. org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer,\
  52. org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
  53. org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
  54. org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
  55. org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
  56. org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
  57. org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
  58. org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
  59. org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
  60. org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
  61. org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
  62. org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
  63. org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
  64. org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
  65. org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer,\
  66. org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer,\
  67. org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer
  68. # 失败分析报告器
  69. org.springframework.boot.diagnostics.FailureAnalysisReporter=\
  70. org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

1. 日志系统

  1. org.springframework.boot.logging.LoggingSystemFactory=\
  2. org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
  3. org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
  4. org.springframework.boot.logging.java.JavaLoggingSystem.Factory

配置中说明 SpringBoot 内置支持 logbacklogbackjava原生三种日志处理,具体源代码可以自行探索

2. 属性来源加载器

  1. org.springframework.boot.env.PropertySourceLoader=\
  2. org.springframework.boot.env.PropertiesPropertySourceLoader,\
  3. org.springframework.boot.env.YamlPropertySourceLoader

配置中说明 SpringBoot 内置支持 application*.propertiesapplication*.yaml 两种文件格式加载属性配置来源,具体源代码可以自行探索

3. 配置数据来源解析器 & 配置数据加载器

  1. # 配置数据来源解析器
  2. org.springframework.boot.context.config.ConfigDataLocationResolver=\
  3. org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
  4. org.springframework.boot.context.config.StandardConfigDataLocationResolver
  5. # 配置数据加载器
  6. org.springframework.boot.context.config.ConfigDataLoader=\
  7. org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
  8. org.springframework.boot.context.config.StandardConfigDataLoader

这一组放在一起解析,是因为他们一起完成了一个功能:

  1. ConfigDataLocationResolver
    spring.config.importspring.config.addtional-locationspring.config.location 等资源定位路径下的
    application*.[properties/yaml] 资源解析成 ConfigDataResource
    资源对象,等待加载
  2. ConfigDataLoader
    将解析好的资源对象进行加载,把 ConfigDataResource 转换成 ConfigData
    ConfigData 是一组 PropertySource
  3. 将加载好的 ConfigData 添加到上下文对象中

ConfigTreeConfigDataLocationResolver
ConfigTreeConfigDataLoader
主要是读取 Kubernetes Volume 的 configMap 配置,这里就不做解析了

3.1. StandardConfigDataLocationResolver

StandardConfigDataLocationResolver
的主要功能是解析外部配置文件

  1. public class StandardConfigDataLocationResolver
  2. implements ConfigDataLocationResolver<StandardConfigDataResource>, Ordered {
  3. public StandardConfigDataLocationResolver(Log logger, Binder binder, ResourceLoader resourceLoader) {
  4. // 加载 `spring.factories` 中的属性加载器,properties+yaml
  5. this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
  6. getClass().getClassLoader());
  7. // 获取 `spring.config.name` 指定的应用名称,默认是 `application`
  8. this.configNames = getConfigNames(binder);
  9. // ... 代码省略
  10. }
  11. // 解析路径 location
  12. @Override
  13. public List<StandardConfigDataResource> resolve(ConfigDataLocationResolverContext context,
  14. ConfigDataLocation location) throws ConfigDataNotFoundException {
  15. // 获取数据引用,然后解析
  16. return resolve(getReferences(context, location));
  17. }
  18. // 获取数据引用
  19. private Set<StandardConfigDataReference> getReferences(ConfigDataLocationResolverContext context,
  20. ConfigDataLocation configDataLocation) {
  21. // 获取资源位置
  22. String resourceLocation = getResourceLocation(context, configDataLocation);
  23. try {
  24. // 如果是目录,就按目录加载
  25. if (isDirectory(resourceLocation)) {
  26. // 加载目录下所有的 application*.[properties/yaml] 文件配置
  27. return getReferencesForDirectory(configDataLocation, resourceLocation, NO_PROFILE);
  28. }
  29. // 不然就按文件加载,获取指定文件的引用
  30. return getReferencesForFile(configDataLocation, resourceLocation, NO_PROFILE);
  31. }
  32. catch (RuntimeException ex) {
  33. // ... 代码省略
  34. }
  35. }
  36. // 解析路径 location 中指定profile的文件
  37. @Override
  38. public List<StandardConfigDataResource> resolveProfileSpecific(ConfigDataLocationResolverContext context,
  39. ConfigDataLocation location, Profiles profiles) {
  40. // 获取数据引用,然后解析
  41. return resolve(getProfileSpecificReferences(context, location, profiles));
  42. }
  43. // 获取指定profile的数据引用
  44. private Set<StandardConfigDataReference> getProfileSpecificReferences(ConfigDataLocationResolverContext context,
  45. ConfigDataLocation configDataLocation, Profiles profiles) {
  46. Set<StandardConfigDataReference> references = new LinkedHashSet<>();
  47. // 获取资源位置
  48. String resourceLocation = getResourceLocation(context, configDataLocation);
  49. // 遍历profiles加载
  50. for (String profile : profiles) {
  51. references.addAll(getReferences(configDataLocation, resourceLocation, profile));
  52. }
  53. return references;
  54. }
  55. }
  1. public class StandardConfigDataLocationResolver
  2. implements ConfigDataLocationResolver<StandardConfigDataResource>, Ordered {
  3. // 获取资源位置
  4. private String getResourceLocation(ConfigDataLocationResolverContext context,
  5. ConfigDataLocation configDataLocation) {
  6. // 去掉"resource:"前缀
  7. String resourceLocation = configDataLocation.getNonPrefixedValue(PREFIX);
  8. // 如果是以 / 开头或者是 [protocol]: 开头的,就算是绝对路径,直接返回
  9. boolean isAbsolute = resourceLocation.startsWith("/") || URL_PREFIX.matcher(resourceLocation).matches();
  10. if (isAbsolute) {
  11. return resourceLocation;
  12. }
  13. // 否则以相对路径对待,加载父路径前缀再返回
  14. ConfigDataResource parent = context.getParent();
  15. if (parent instanceof StandardConfigDataResource) {
  16. String parentResourceLocation = ((StandardConfigDataResource) parent).getReference().getResourceLocation();
  17. String parentDirectory = parentResourceLocation.substring(0, parentResourceLocation.lastIndexOf("/") + 1);
  18. return parentDirectory + resourceLocation;
  19. }
  20. return resourceLocation;
  21. }
  22. // 解析StandardConfigDataReference为StandardConfigDataResource
  23. private List<StandardConfigDataResource> resolve(Set<StandardConfigDataReference> references) {
  24. List<StandardConfigDataResource> resolved = new ArrayList<>();
  25. for (StandardConfigDataReference reference : references) {
  26. resolved.addAll(resolve(reference));
  27. }
  28. if (resolved.isEmpty()) {
  29. resolved.addAll(resolveEmptyDirectories(references));
  30. }
  31. return resolved;
  32. }
  33. }

3.2. StandardConfigDataLoader

StandardConfigDataLoader
的主要功能是读取外部配置文件里的值

  1. public class StandardConfigDataLoader implements ConfigDataLoader<StandardConfigDataResource> {
  2. // 加载文件为ConfigData
  3. @Override
  4. public ConfigData load(ConfigDataLoaderContext context, StandardConfigDataResource resource)
  5. throws IOException, ConfigDataNotFoundException {
  6. // ... 代码省略
  7. StandardConfigDataReference reference = resource.getReference();
  8. Resource originTrackedResource = OriginTrackedResource.of(resource.getResource(),
  9. Origin.from(reference.getConfigDataLocation()));
  10. String name = String.format("Config resource '%s' via location '%s'", resource,
  11. reference.getConfigDataLocation());
  12. // 读取为propertySources
  13. List<PropertySource<?>> propertySources = reference.getPropertySourceLoader().load(name, originTrackedResource);
  14. return new ConfigData(propertySources);
  15. }
  16. }

4. 应用运行监听器

  1. org.springframework.boot.SpringApplicationRunListener=\
  2. org.springframework.boot.context.event.EventPublishingRunListener

EventPublishingRunListener
的主要功能是发布应用事件,调用事件监听函数

5. 错误报告器

  1. org.springframework.boot.SpringBootExceptionReporter=\
  2. org.springframework.boot.diagnostics.FailureAnalyzers

FailureAnalyzers
的主要功能是向用户报告程序错误

6. 应用上下文初始加载器

  1. org.springframework.context.ApplicationContextInitializer=\
  2. org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
  3. org.springframework.boot.context.ContextIdApplicationContextInitializer,\
  4. org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
  5. org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
  6. org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

这些类都比较简单,以 ConfigurationWarningsApplicationContextInitializer
为例解析

  1. public class ConfigurationWarningsApplicationContextInitializer
  2. implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  3. // 初始化组件
  4. @Override
  5. public void initialize(ConfigurableApplicationContext context) {
  6. context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
  7. }
  8. protected static final class ConfigurationWarningsPostProcessor
  9. implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {
  10. // bean定义后置处理
  11. @Override
  12. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  13. for (Check check : this.checks) {
  14. // 如果 @ComponentScan 扫描了 org.springframework 或 org,则警告错误
  15. String message = check.getWarning(registry);
  16. if (StringUtils.hasLength(message)) {
  17. warn(message);
  18. }
  19. }
  20. }
  21. }
  22. }

7. 应用监听器

  1. org.springframework.context.ApplicationListener=\
  2. org.springframework.boot.ClearCachesApplicationListener,\
  3. org.springframework.boot.builder.ParentContextCloserApplicationListener,\
  4. org.springframework.boot.context.FileEncodingApplicationListener,\
  5. org.springframework.boot.context.config.AnsiOutputApplicationListener,\
  6. org.springframework.boot.context.config.DelegatingApplicationListener,\
  7. org.springframework.boot.context.logging.LoggingApplicationListener,\
  8. org.springframework.boot.env.EnvironmentPostProcessorApplicationListener

这些类都比较简单,可以自行探索

8. 环境后置处理器

  1. org.springframework.boot.env.EnvironmentPostProcessor=\
  2. org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
  3. org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
  4. org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
  5. org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
  6. org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
  7. org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor

8.1. CloudFoundryVcapEnvironmentPostProcessor

CloudFoundryVcapEnvironmentPostProcessor
的主要功能是支持 CloudFoundry(一个开源 PaaS 云平台)

8.2. ConfigDataEnvironmentPostProcessor

ConfigDataEnvironmentPostProcessor
的主要功能是加载和应用 ConfigData 到 Spring 环境中

  1. public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
  2. @Override
  3. public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
  4. postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
  5. }
  6. void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
  7. Collection<String> additionalProfiles) {
  8. try {
  9. // 获取资源加载器
  10. resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
  11. // 加载和应用
  12. getConfigDataEnvironment(environment, resourceLoader, additionalProfiles).processAndApply();
  13. }
  14. catch (UseLegacyConfigProcessingException ex) {
  15. // ... 代码省略
  16. }
  17. }
  18. // 获取环境对象
  19. ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
  20. Collection<String> additionalProfiles) {
  21. return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader,
  22. additionalProfiles, this.environmentUpdateListener);
  23. }
  24. }

实际加载与应用是由 ConfigDataEnvironment
完成的

  1. class ConfigDataEnvironment {
  2. // 用于覆盖默认属性加载的地方
  3. static final String LOCATION_PROPERTY = "spring.config.location";
  4. // 默认之外,其他属性加载的地方
  5. static final String ADDITIONAL_LOCATION_PROPERTY = "spring.config.additional-location";
  6. // 导入第三方属性文件
  7. static final String IMPORT_PROPERTY = "spring.config.import";
  8. // 默认属性加载的地方
  9. // 1. 加载 classpath:/application*.yaml
  10. // 2. 加载 classpath:/config/application*.yaml
  11. // 3. 加载 file:./application*.yaml
  12. // 4. 加载 file:./config/application*.yaml
  13. // 5. 加载 file:./config/*/application*.yaml
  14. static final ConfigDataLocation[] DEFAULT_SEARCH_LOCATIONS;
  15. static {
  16. List<ConfigDataLocation> locations = new ArrayList<>();
  17. locations.add(ConfigDataLocation.of("optional:classpath:/"));
  18. locations.add(ConfigDataLocation.of("optional:classpath:/config/"));
  19. locations.add(ConfigDataLocation.of("optional:file:./"));
  20. locations.add(ConfigDataLocation.of("optional:file:./config/"));
  21. locations.add(ConfigDataLocation.of("optional:file:./config/*/"));
  22. DEFAULT_SEARCH_LOCATIONS = locations.toArray(new ConfigDataLocation[0]);
  23. }
  24. // 属性值提供器
  25. private final ConfigDataEnvironmentContributors contributors;
  26. ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
  27. ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
  28. ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
  29. // ... 代码省略
  30. // 创建默认的属性值提供器
  31. this.contributors = createContributors(binder);
  32. }
  33. // 创建默认的属性值提供器
  34. private ConfigDataEnvironmentContributors createContributors(Binder binder) {
  35. // 获取属性值来源
  36. MutablePropertySources propertySources = this.environment.getPropertySources();
  37. // 结果集
  38. List<ConfigDataEnvironmentContributor> contributors = new ArrayList<>(propertySources.size() + 10);
  39. // 默认的属性值来源
  40. PropertySource<?> defaultPropertySource = null;
  41. for (PropertySource<?> propertySource : propertySources) {
  42. // default properties
  43. if (DefaultPropertiesPropertySource.hasMatchingName(propertySource)) {
  44. defaultPropertySource = propertySource;
  45. }
  46. // 其他的
  47. else {
  48. contributors.add(ConfigDataEnvironmentContributor.ofExisting(propertySource));
  49. }
  50. }
  51. // 获取默认的提供器
  52. contributors.addAll(getInitialImportContributors(binder));
  53. // 如果有默认的,添加到最后面
  54. if (defaultPropertySource != null) {
  55. contributors.add(ConfigDataEnvironmentContributor.ofExisting(defaultPropertySource));
  56. }
  57. // 创建 ConfigDataEnvironmentContributors
  58. return createContributors(contributors);
  59. }
  60. // 获取默认的提供器
  61. private List<ConfigDataEnvironmentContributor> getInitialImportContributors(Binder binder) {
  62. // 结果集
  63. List<ConfigDataEnvironmentContributor> initialContributors = new ArrayList<>();
  64. // 添加 `spring.config.import` 指定的资源
  65. addInitialImportContributors(initialContributors, bindLocations(binder, IMPORT_PROPERTY, EMPTY_LOCATIONS));
  66. // 添加 `spring.config.additional-location` 指定的资源
  67. addInitialImportContributors(initialContributors,
  68. bindLocations(binder, ADDITIONAL_LOCATION_PROPERTY, EMPTY_LOCATIONS));
  69. // 添加 `spring.config.location` 指定的资源
  70. // (会覆盖默认属性加载的地方:classpath:/, classpath:/config/, file:./, file:./config/, file:./config/*/)
  71. addInitialImportContributors(initialContributors,
  72. bindLocations(binder, LOCATION_PROPERTY, DEFAULT_SEARCH_LOCATIONS));
  73. return initialContributors;
  74. }
  75. }
  1. class ConfigDataEnvironment {
  2. // 处理及应用
  3. void processAndApply() {
  4. // 创建 ConfigDataImporter
  5. ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, this.notFoundAction, this.resolvers,
  6. this.loaders);
  7. // 绑定 contributors
  8. registerBootstrapBinder(this.contributors, null, DENY_INACTIVE_BINDING);
  9. // 导入 `spring.config.import` 指定的资源,重新绑定 contributors
  10. ConfigDataEnvironmentContributors contributors = processInitial(this.contributors, importer);
  11. // 创建一个配置数据激活上下文对象,如果绑定到了没有active的属性源,则报错
  12. // 比如:spring.profiles.active=prod,但绑定了 application-dev.yaml
  13. ConfigDataActivationContext activationContext = createActivationContext(
  14. contributors.getBinder(null, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
  15. // 导入无 profile `application.yaml` 的资源,重新绑定 contributors
  16. contributors = processWithoutProfiles(contributors, importer, activationContext);
  17. // 载入profiles到绑定的上下文中
  18. activationContext = withProfiles(contributors, activationContext);
  19. // 导入激活 profile `application-[active].yaml` 的资源,重新绑定 contributors
  20. contributors = processWithProfiles(contributors, importer, activationContext);
  21. // 应用到环境中
  22. applyToEnvironment(contributors, activationContext);
  23. }
  24. // 导入 `spring.config.import` 指定的资源,重新绑定 contributors
  25. private ConfigDataEnvironmentContributors processInitial(ConfigDataEnvironmentContributors contributors,
  26. ConfigDataImporter importer) {
  27. contributors = contributors.withProcessedImports(importer, null);
  28. registerBootstrapBinder(contributors, null, DENY_INACTIVE_BINDING);
  29. return contributors;
  30. }
  31. // 导入无 profile `application.yaml` 的资源,重新绑定 contributors
  32. private ConfigDataEnvironmentContributors processWithoutProfiles(ConfigDataEnvironmentContributors contributors,
  33. ConfigDataImporter importer, ConfigDataActivationContext activationContext) {
  34. contributors = contributors.withProcessedImports(importer, activationContext);
  35. registerBootstrapBinder(contributors, activationContext, DENY_INACTIVE_BINDING);
  36. return contributors;
  37. }
  38. // 载入profiles到绑定的上下文中
  39. private ConfigDataActivationContext withProfiles(ConfigDataEnvironmentContributors contributors,
  40. ConfigDataActivationContext activationContext) {
  41. // 获取绑定对象
  42. Binder binder = contributors.getBinder(activationContext,
  43. ConfigDataEnvironmentContributor::isNotIgnoringProfiles, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
  44. try {
  45. // 参数输入的profiles
  46. Set<String> additionalProfiles = new LinkedHashSet<>(this.additionalProfiles);
  47. // 载入当前激活环境中 `spring.profiles.include` 指定的其他环境
  48. additionalProfiles.addAll(getIncludedProfiles(contributors, activationContext));
  49. // 创建 Profiles 对象,载入到上下文中
  50. Profiles profiles = new Profiles(this.environment, binder, additionalProfiles);
  51. return activationContext.withProfiles(profiles);
  52. }
  53. catch (BindException ex) {
  54. // ... 代码省略
  55. }
  56. }
  57. // 导入激活 profile `application-[active].yaml` 的资源,重新绑定 contributors
  58. private ConfigDataEnvironmentContributors processWithProfiles(ConfigDataEnvironmentContributors contributors,
  59. ConfigDataImporter importer, ConfigDataActivationContext activationContext) {
  60. contributors = contributors.withProcessedImports(importer, activationContext);
  61. registerBootstrapBinder(contributors, activationContext, ALLOW_INACTIVE_BINDING);
  62. return contributors;
  63. }
  64. // 应用到环境中
  65. private void applyToEnvironment(ConfigDataEnvironmentContributors contributors,
  66. ConfigDataActivationContext activationContext) {
  67. // ... 代码省略
  68. // 属性来源
  69. MutablePropertySources propertySources = this.environment.getPropertySources();
  70. // 遍历contributors
  71. for (ConfigDataEnvironmentContributor contributor : contributors) {
  72. PropertySource<?> propertySource = contributor.getPropertySource();
  73. // ... 代码省略
  74. // 如果是激活的,加入到环境的propertySources中
  75. if (contributor.isActive(activationContext)) {
  76. propertySources.addLast(propertySource);
  77. }
  78. }
  79. // ... 代码省略
  80. }
  81. }

实际资源载入是由 ConfigDataEnvironmentContributors
完成的

  1. class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmentContributor> {
  2. // 处理载入属性值
  3. ConfigDataEnvironmentContributors withProcessedImports(ConfigDataImporter importer,
  4. ConfigDataActivationContext activationContext) {
  5. // 每次载入新的文件后,都返回一个新的对象
  6. ConfigDataEnvironmentContributors result = this;
  7. int processed = 0;
  8. while (true) {
  9. // 获取下一个可以载入的文件
  10. ConfigDataEnvironmentContributor contributor = getNextToProcess(result, activationContext, importPhase);
  11. // 没有下一个了,返回
  12. if (contributor == null) {
  13. return result;
  14. }
  15. // 非导入其他文件
  16. if (contributor.getKind() == Kind.UNBOUND_IMPORT) {
  17. // 配置属性源
  18. Iterable<ConfigurationPropertySource> sources = Collections
  19. .singleton(contributor.getConfigurationPropertySource());
  20. // 占位符解析器
  21. PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(
  22. result, activationContext, true);
  23. // 新建绑定
  24. Binder binder = new Binder(sources, placeholdersResolver, null, null, null);
  25. // 生成一个新的ConfigDataEnvironmentContributor
  26. ConfigDataEnvironmentContributor bound = contributor.withBoundProperties(binder);
  27. // 生成一个新的对象
  28. result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapContext,
  29. result.getRoot().withReplacement(contributor, bound));
  30. continue;
  31. }
  32. // 路径解析上下文
  33. ConfigDataLocationResolverContext locationResolverContext = new ContributorConfigDataLocationResolverContext(
  34. result, contributor, activationContext);
  35. // 加载上下文
  36. ConfigDataLoaderContext loaderContext = new ContributorDataLoaderContext(this);
  37. // 获取导入的资源路径
  38. List<ConfigDataLocation> imports = contributor.getImports();
  39. // 导入资源为ConfigData
  40. Map<ConfigDataResolutionResult, ConfigData> imported = importer.resolveAndLoad(activationContext,
  41. locationResolverContext, loaderContext, imports);
  42. // 合并当前与上一次的属性值
  43. ConfigDataEnvironmentContributor contributorAndChildren = contributor.withChildren(importPhase,
  44. asContributors(imported));
  45. // 生成一个新的对象
  46. result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapContext,
  47. result.getRoot().withReplacement(contributor, contributorAndChildren));
  48. processed++;
  49. }
  50. }
  51. }

8.3. CloudFoundryVcapEnvironmentPostProcessor

CloudFoundryVcapEnvironmentPostProcessor
的主要功能是支持以random.开头的属性配置转换成实际的随机值

8.4. SpringApplicationJsonEnvironmentPostProcessor

SpringApplicationJsonEnvironmentPostProcessor
的主要功能是支持用 spring.application.json 参数或 SPRING_APPLICATION_JSON 环境变量作为初始化参数传入 JSON 数据

  1. public class SpringApplicationJsonEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
  2. @Override
  3. public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
  4. // 获取属性来源
  5. MutablePropertySources propertySources = environment.getPropertySources();
  6. // 流式处理 `spring.application.json` 参数或 `SPRING_APPLICATION_JSON` 环境变量
  7. propertySources.stream().map(JsonPropertyValue::get).filter(Objects::nonNull).findFirst()
  8. .ifPresent((v) -> processJson(environment, v));
  9. }
  10. private void processJson(ConfigurableEnvironment environment, JsonPropertyValue propertyValue) {
  11. // 获取JSON解析器
  12. JsonParser parser = JsonParserFactory.getJsonParser();
  13. // 解析成Map
  14. Map<String, Object> map = parser.parseMap(propertyValue.getJson());
  15. // 有值
  16. if (!map.isEmpty()) {
  17. // 添加为一个JSON来源
  18. addJsonPropertySource(environment, new JsonPropertySource(propertyValue, flatten(map)));
  19. }
  20. }
  21. }
  1. public abstract class JsonParserFactory {
  2. public static JsonParser getJsonParser() {
  3. // 默认首先使用Jackson
  4. if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
  5. return new JacksonJsonParser();
  6. }
  7. // 其次使用Gson
  8. if (ClassUtils.isPresent("com.google.gson.Gson", null)) {
  9. return new GsonJsonParser();
  10. }
  11. // 其次使用Yaml
  12. if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
  13. return new YamlJsonParser();
  14. }
  15. // 都没有,使用内置的
  16. return new BasicJsonParser();
  17. }
  18. }

8.5. SystemEnvironmentPropertySourceEnvironmentPostProcessor

SystemEnvironmentPropertySourceEnvironmentPostProcessor
的主要功能是处理 systemEnvironment 属性来源

8.6. DebugAgentEnvironmentPostProcessor

DebugAgentEnvironmentPostProcessor
的主要功能是处理 spring.reactor.debug-agent.enabled

9. 失败分析器

  1. org.springframework.boot.diagnostics.FailureAnalyzer=\
  2. org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer,\
  3. org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer,\
  4. org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
  5. org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
  6. org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
  7. org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
  8. org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
  9. org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
  10. org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
  11. org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
  12. org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
  13. org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
  14. org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
  15. org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
  16. org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
  17. org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer,\
  18. org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer,\
  19. org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer

这些类都比较简单,可以自行探索

10. 失败分析报告器

  1. org.springframework.boot.diagnostics.FailureAnalysisReporter=\
  2. org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

LoggingFailureAnalysisReporter
的主要功能是应用启动失败,报告原因 APPLICATION FAILED TO START

后续

更多博客,查看 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证

相关文章