美文网首页
Springboot 启动加载机制

Springboot 启动加载机制

作者: 雪飘千里 | 来源:发表于2019-12-25 11:20 被阅读0次

Spring boot最大的好处就是遵从了java约定大于配置不用面对一大堆的配置文件,spring boot是根据你用的包来决定提供什么配置。

springBoot的启动可以分为两个部分,第一部分:SpringApplication的实例化;第二部分:调用该实例运行run方法(springboot初始化)。

1、SpringApplication的实例化

1.1 判断是否为webEnvironment

private void initialize(Object[] sources) {
    if (sources != null && sources.length > 0) {
      this.sources.addAll(Arrays.asList(sources));
    }
    //判定是否为webEnvironment
    this.webEnvironment = deduceWebEnvironment();
  
    //使用SpringFactoriesLoader在JAR包中META-INF/spring.factories文件中,查找key为ApplicationContextInitializer对应的class,
    //并实例化加载所有可用的ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
//使用SpringFactoriesLoader在JAR包中META-INF/spring.factories文件中,查找key为ApplicationListener对应的class,
 //并实例化加载所有可用的ApplicationListener
    setListeners((Collection)
    getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
  }

1.2 实例化并加载所有可以加载的ApplicationContextInitializer

ApplicationContextInitializer:当springboot上下文Context初始化完成后会调用

1.3 实例化并加载所有可以加载的监听器ApplicationListener

ApplicationListener:当springboot启动时事件change后都会触发

image.png

2、调用该实例运行run方法。

spring boot 初始化内容还是很多的,但是总结起来就四点:

  • 2.1 通过SpringFactoriesLoader获取所有的SpringApplicationRunListeners(其实内部只有一个EventPublishingRunListener),调用它们的started()方法,
    发布/广播 Springboot启动事件(ApplicationStartingEvent)
    也就是说,把springboot启动事件封装成SpringApplicationEvent事件,然后广播出去给SpringApplication中的所有listeners
//org.springframework.boot.context.event.EventPublishingRunListener#running
    @Override
    public void starting() {
        this.initialMulticaster.multicastEvent(
                new ApplicationStartingEvent(this.application, this.args));
    }
  • 2.2 加载环境变量,环境变量包括system environment、classpath environment、application environment(也就是我们自定义的application.properties配置文件),并发布ApplicationEnvironmentPreparedEvent事件
  • 2.3 创建ApplicationContext
    对ApplicationContext设置环境变量;
    配置属性ResourceLoader和ClassLoader属性;
    遍历继承1.2步骤中获取的所有继承ApplicationContextInitializer接口的类,循环调用initialize()初始化方法;
    发布ApplicationPreparedEvent事件;

  • 2.4 刷新应用上下文ApplicationContext
    这里是ApplicationContext真正开始初始化容器和创建bean的阶段,其中bean的整个生命周期可以从这一步骤看出来;Spring Framework中的所有ApplicationContext实现都直接或间接继承自AbstracttApplicationContext,它的refresh方法描述了整个上下文的初始化逻辑。
    2.4.1:准备更新上下文时的预备工作;
    2.4.2:获取上下文的内部BeanFactory;
    2.4.3:对BeanFactory做些预备工作;
    2.4.4:对BeanFactory进行预处理;
    2.4.5:执行容器中的BeanFactoryPostProcessor;
    2.4.6:注册BeanPostProcessor;
    BeanPostProcessor:Bean生命周期的钩子,允许用户对实例化后的Bean进行操作
    2.4.7:初始化MessageSource(国际化相关)//忽略;
    2.4.8:初始化容器事件广播器(用来发布事件);
    2.4.9:初始化一些特殊的Bean;
    2.4.10:将所有监听器注册到前两步创建的事件广播器中;
    2.4.11:结束BeanFactory的初始化工作;
    这一步主要用来将所有的单例BeanDefinition实例化
    2.4.12:afterRefresh(上下文刷新完毕);

即,初始化BeanFactory,加载bean,启动内置web容器;
发布ContextRefreshedEvent事件;

//AbstractApplicationContext的refresh方法
synchronized (this.startupShutdownMonitor) {
                prepareRefresh();//(1)
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//(2)
                prepareBeanFactory(beanFactory);//(3)
                try {
                    postProcessBeanFactory(beanFactory);//(4)
                    invokeBeanFactoryPostProcessors(beanFactory);//(5)
                    registerBeanPostProcessors(beanFactory);//(6)
                    initMessageSource();//(7)
                    initApplicationEventMulticaster();//(8)
                    onRefresh();//(9)
                    registerListeners();//(10)
                    finishBeanFactoryInitialization(beanFactory);//(11)
                    finishRefresh();//(12)
                }catch (BeansException ex) {
                    //。。。。。。
                }
                finally {
                    resetCommonCaches();
                }
}
  • 2.5 发布/广播 ApplicationStartedEvent事件

  • 2.6 发布/广播 ApplicationReadyEvent 事件

  • 2.7 启动完成

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
//2.1  获取SpringApplicationRunListeners
        SpringApplicationRunListeners listeners = getRunListeners(args);
// 广播/发布 SpringApplicationEvent事件
        listeners.starting();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
//2.2 加载环境变量
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
//2.3 创建ApplicationContext
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
//2.4 刷新上下文ApplicationContext
            refreshContext(context);
// 发布ContextRefreshedEvent事件;
            afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
//2.5   发布/广播 ApplicationStartedEvent事件
            listeners.started(context);
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }

        try {
//2.6 发布/广播 ApplicationReadyEvent 事件
            listeners.running(context);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }
image.png

相关文章

网友评论

      本文标题:Springboot 启动加载机制

      本文链接:https://www.haomeiwen.com/subject/bnyxgctx.html