前置了解

Environment

本身是一个PropertyResolver,但是提供了Profile特性,即可以根据环境得到相应数据(即激活不同的Profile,可以得到不同的属性数据,用于多环境场景的配置。我们分析Spring Boot的启动流程,以创建StandardServletEnvironment为例:
image.png
PropertySource
属性源,key-value属性对抽象,比如用于配置数据。
image.png
PropertyResolver
属性解析器,用于解析相应key的value。
image.png
image.png
image.png
Profile
剖面,只有激活的剖面的组件/配置才会注册到Spring容器

Context

上下文,这个上下文由多种数据结构组成,可以提供我们运行时需要的一些数据和保存运行时的一些数据,context 可以理解对一个程序运行时所需要的一些数据结构的抽象表达。
Spring Boot的启动流程中申明创建了ConfigurableApplicationContext(实际的类型为AnnotationConfigServletWebServerApplicationContext
image.png

组成

  • environment:所属AbstractApplicationContext,是将上一步的prepareEnvironment()中的environment赋值给Context中变量。

主流程

我将SpringApplication#run()主流程分为#getRunListeners#prepareEnvironment#prepareContext#refreshContext#afterRefresh这5部分,本篇讲解的Spring加载配置,与Environment和Context两个类关联紧密,主要讲解#prepareEnvironment#prepareContext

SpringApplication#run().png

1. #getRunListeners

获取EventPublishingRunListener,该Listener对象内包含成员变量SimpleApplicationEventMulticaster,用于广播后续流程中的事件。

2. #prepareEnvironment

#prepareEnvironment方法内分为#getOrCreateEnvironment#configureEnvironmentlisteners#environmentPrepared3个部分。

2.1 #getOrCreateEnvironment

根据webApplicationType生成环境类new StandardServletEnvironment()。在构造方法中会封装成员变量propertySourcespropertyResolver。封装的propertySources为systemEnvironment�、systemProperties�、servletConfigInitParams、servletContextInitParams

2.2 #configureEnvironment

封装环境信息分为

  • configurePropertySources,添加、删除、重排PropertySource
  • configureProfiles,配置activeProfiles

    2.3 listeners#environmentPrepared

    EventPublishingRunListener通过initialMulticaster
    �发布ApplicationEnvironmentPreparedEvent事件,然后通过event和eventType获取监听的listeners,listener基于同步的方式处理事件,此处是ConfigFileApplicationListener处理该事件。ConfigFileApplicationListener中包含数个EnvironmentPostProcessor环境准备完的后置处理。
    image.png

    3. #prepareContext

    3.1 context.setEnvironment(environment)

    将createApplicationContext()创建的context的变量environment赋值。

    �3.2 postProcessApplicationContext(context)

    � 后置处理ApplicationContext,设置context的类型转换ConversionServicecontext.getBeanFactory().setConversionService(xxx)


其他细节

监听器部分使用了观察者模式,回调的实现是在ApplicationEventMulticaster在广播时候(调用multicastEvent�方法)�中实现的,以子类SimpleApplicationEventMulticaster为例,最终调用#doInvokeListener代码如下:

  1. @SuppressWarnings({"rawtypes", "unchecked"})
  2. private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
  3. try {
  4. listener.onApplicationEvent(event);
  5. }
  6. catch (ClassCastException ex) {
  7. String msg = ex.getMessage();
  8. if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
  9. // Possibly a lambda-defined listener which we could not resolve the generic event type for
  10. // -> let's suppress the exception and just log a debug message.
  11. Log logger = LogFactory.getLog(getClass());
  12. if (logger.isTraceEnabled()) {
  13. logger.trace("Non-matching event type for listener: " + listener, ex);
  14. }
  15. }
  16. else {
  17. throw ex;
  18. }
  19. }
  20. }

参考

【1】:https://zhuanlan.zhihu.com/p/48030077
【2】:https://www.cnblogs.com/yourbatman/p/14061177.html
【3】:https://blog.csdn.net/dkyaoyao/article/details/84819519