springboot

springboot

Posted by XJ on February 1, 2023

springboot 启动

1. 获取、启动运行过程中的监听器
run方法    SpringApplicationRunListeners listeners = this.getRunListeners(args);
getRunListeners() 方法   然后调用 
getSpringFactoriesInstances()方法   
然后loadFactoryNamesd读取spring.factory里面的事例
最后注册  EventPublishingRunListener 
EventPublishingRunListener的方法用来触发 SpringApplicationEvent中的不同子类
总结: 这一步其实就是广播了ApplicationStartingEvent事件来触发监听这个事件的ApplicationListener

2:环境构建
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
环境构建这一步加载了   系统环境配置、用户自定义配置   并且广播了ApplicationEnvironmentPreparedEvent事件,触发监听器

3. 创建IOC容器
context = createApplicationContext();
根据webApplicationType 决定创建的类型  
这里是servlet 所以是  AnnotationConfigServletWebServerApplicationContext
    switch(this.webApplicationType) {
            case SERVLET:
                contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                break;
            case REACTIVE:
                contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                break;
            default:
                contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
            }

4. IOC容器的前置处理
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
a、设置环境参数
b、执行后置处理
c、执行初始化器
d、设置banner
e、广播容器准备完成事件,触发监听器
f、获取启动累制定的参数  可有多个
     g、加载启动类  将启动类注入容器    加入到 beanDefinitionMap
h、发布容器已加载事件
在刷新容器之前做准备,其中有一个非常关键的操作:将启动类注入容器,为后续的自动化配置奠定基础

5. 刷新容器
初始化资源,初始化上下文广播器

6. IOC容器的后置处理
afterRefresh(context, applicationArguments);
默认为空,如果有自定义需求可以重写,比如打印一些启动结束日志等。

7. 发出结束执行的事件

同样是EventPublishingRunListener这个监听器,广播ApplicationStartedEvent事件
但是这里广播事件和前几次不同,并不是广播给SpringApplication中的监听器(在构建过程中从spring.factories文件获取的监听器)
。因此在IOC容器中注入的监听器(使用@Component等方式注入的)也能够生效。前面几个事件只有在spring.factories文件中设置的监听器才会生效

8.执行runners
callRunners(context, applicationArguments);
有两种     
ApplicationRunner
CommandLineRunner



springApplication方法

获取、启动运行过程中的监听器  ---->  环境构建  ---->  ️创建IOC容器     
                                                        |
                                                        |
                                                        |
IOC容器后置处理    <----    创建IOC容器   <----   IOC容器前置处理
      |
      |
      |
 发出结束执行的事件 ---- >   ️执行runners


public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    this.configureHeadlessProperty();
    1⃣️获取、启动运行过程监听器
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting();

    Collection exceptionReporters;
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        2⃣️环境构建
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        this.configureIgnoreBeanInfo(environment);
        Banner printedBanner = this.printBanner(environment);
        3⃣️创建IOC容器
        context = this.createApplicationContext();
        exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
        4⃣️IOC容器前置处理
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        5⃣️刷新容器
        this.refreshContext(context);
        6⃣️IOC容器后置处理
        this.afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }
        7⃣️发出结束执行的事件
        listeners.started(context);
        8⃣️执行runners
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, exceptionReporters, listeners);
        throw new IllegalStateException(var10);
    }

    try {
        listeners.running(context);
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}