【SpringBoot】启动过程之——SpringApplication初始化及运行

目录

  • 1. 初始化 SpringApplication
  • 2. 运行 SpringApplication

Spring Boot 工程的主函数

@SpringBootApplication()
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(WhidsSsApplication.class, args);
    }
}

分为了两个部分:

  • 初始化 SpringApplication
new SpringApplication
  • 运行 SpringApplication
springApplication.run()

1. 初始化 SpringApplication

配置基本的环境变量、资源、构造器、监听器。

初始化阶段的主要作用是为运行 SpringApplication 实例对象启动环境变量准备、以及进行资源构造器的初始化动作。

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
   this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   this.mainApplicationClass = deduceMainApplicationClass();
}
  1. setInitializers,实例化所有初始器:
    加载 ApplicationContextInitializer 是在 SpringFactoriesLoader.loadFactoryNames 方法里面进行的。这个方法会尝试从类路径的 META-INF/spring.factories 读取相应配置文件,然后进行遍历,读取配置文件中Key为:org.springframework.context.ApplicationContextInitializer 的 value。
    以 spring-boot 为例,它的 Initializers 定义如下,Initializers 的作用在上一章中已详细解释
# Application Context Initializers
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
  1. setListeners,实例化所有监听器
    同样以 spring-boot 为例,它的 Initializers 定义如下:
# Application Listeners
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

2. 运行 SpringApplication

Spring Boot 正式启动加载过程,包括启动流程监控模块、配置环境加载模块、ApplicationContext 容器上下文环境加载模块。

其中的一些关键步骤:

  1. 发布应用启动过程中的一系列事件
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);

SpringApplicationRunListeners 本质上是一个事件发布者,它在 SpringBoot 应用启动的不同时间点发布不同应用事件类型(ApplicationEvent):

由上文知在初始化的流程中,SpringApplication 加载了一系列 ApplicationListener,其监听的事件就是在这里发布的。

  1. 创建应用程序上下文
    ApplicationContext,也就是我们所说的 Spring Ioc 容器,是在 BeanFactory 的基础之上的一种更高级的容器,除了具有基本的 bean 管理功能之外,还提供对事件监听机制以及国际化的支持等。
context = createApplicationContext();
  1. 准备ApplicationContext
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

主要完成以下工作:

  • 实例化单例的 BeanNameGenerator
// public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
//      "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
      
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
      this.beanNameGenerator);

Spring 定义 bean 有两种模式:配置文件(xml,properties)和注解。BeanNameGenerator 是为 bean 定义生成 bean 名称的策略接口。
其实现类有两个:
DefaultBeanNameGenerator :用来处理 xml 资源文件,但一般情况下在 Spring Boot 中我们很少使用 xml 来引入 bean;
AnnotationBeanNameGenerator :处理 @Component 等注解生成 bean name。当注解中有 value 属性时,则给 bean 命名为 value 值。当没有指定名称时,则根据类名自动生成。

  • 执行初始化方法。在初始化阶段中我们加载了所有的 ApplicationContextInitializer ,依次执行
initializer.initialize(context);
  • 发布事件,通知监听者 ApplicationContext 已经准备完毕
listeners.contextLoaded(context);

void contextLoaded(ConfigurableApplicationContext context) {
   doWithListeners("spring.boot.application.context-loaded", (listener) -> listener.contextLoaded(context));
}
  • 将所有的bean加载到容器中
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
  • 再次发布事件,通知监听者 ApplicationContext 已经装载完毕
listeners.contextLoaded(context);
  1. 刷新上下文,属于 spring 中的机制,包括了属性自动装配等步骤
refreshContext(context);
  1. 发布上下文准备就绪事件
listeners.started(context);

你可能感兴趣的:(spring,spring,boot,java,spring)