SpringBoot启动

参考文档:https://www.jianshu.com/p/ef6f0c0de38f

1.相关概念

1.1 Spring IOC相关类

BeanFactory
BeanDefinitionRegistry
DefaultListableBeanFactory

BeanDefinition
AbstractBeanDefinition
RootBeanDefinition ChildBeanDefinition

ApplicationContext

1.2 Bean生命周期

  1. 实例化Bean对象
  2. 设置对象属性
  3. 检查Aware相关接口并设置相关依赖
  4. BeanPostProcessor前置处理
  5. 检查是否是InitializingBean
  6. 检查是否配置有自定义的init-method
  7. BeanPostProcessor后置处理
  8. 注册必要的Destruction相关回调接口
  9. 使用中
  10. 检查是否是DisposableBean
  11. 检查是否配置有自定义的destroy方法

1.3 Spring提供的Bean扩展

IOC容器负责管理容器中所有bean的生命周期,而在生命周期的不同阶段,Spring提供提供对应扩展点给到用户进行自定义处理。

生命周期阶段 说明
容器启动阶段 BeanFactoryPostProcessor BeanFactory的前置处理器,允许在容器实例化相应对象前,对注册到容器的BeanDefinition保存信息做额外的操作。
对象示例化阶段 BeanPostProcessor 处理容器内所有符合条件并且已经实例化后的对象
对象实例化完成后 Aware接口 在对象实例化完成后将Aware接口中规定的依赖注入到当前实例中。
如ApplicationContextAware接口,实现了这个接口的类都可以获取到一个ApplicationContext对象。
当容器中每个对象的实例化过程走到BeanPostProcessor前置处理这一步时,容器会检测到之前注册到容器的ApplicationContextAwareProcessor,然后就会调用其postProcessBeforeInitialization()方法,检查并设置Aware相关依赖

1.4 事件监听机制

Java提供了实现事件监听的两个基础类:

  • 自定义事件类型 java.util.EventObject
  • 事件的监听器 java.util.EventListener

Spring的ApplicationContext内部的所有事件类型都继承自org.springframework.context.AppliationEvent,

所有监听器都实现org.springframework.context.ApplicationListener接口,并且以bean的形式注册在容器中,一旦在容器内发布ApplicationEvent及其子类型的事件,注册到容器的ApplicationListener就会对这些事件进行处理。

  1. ApplicationEvent继承自EventObject,Spring提供了一些默认的实现,比如:

    ContextClosedEvent表示容器在即将关闭时发布的事件类型

    ContextRefreshedEvent表示容器在初始化或者刷新的时候发布的事件类型

  2. 容器内部使用ApplicationListener作为事件监听器接口定义,它继承自EventListener。

    ApplicationContext容器在启动时,会自动识别并加载EventListener类型的bean,一旦容器内有事件发布,将通知这些注册到容器的EventListener。

  3. ApplicationContext接口继承了ApplicationEventPublisher接口,该接口提供了void publishEvent(ApplicationEvent event)方法定义,不难看出,ApplicationContext容器担当的就是事件发布者的角色ApplicationContext将事件的发布以及监听器的管理工作委托给ApplicationEventMulticaster接口的实现类。在容器启动时,会检查容器内是否存在名为applicationEventMulticaster的ApplicationEventMulticaster对象实例。如果有就使用其提供的实现,没有就默认初始化一个SimpleApplicationEventMulticaster作为实现。

2.SpringBoot启动流程

启动流程都封装在SpringApplication.run方法中:

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        //1.通过SpringFactoriesLoader查找并加载所有的SpringApplicationRunListeners,通过调用
        //starting()方法通知所有的SpringApplicationRunListeners:应用开始启动了
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            //2.创建并配置当前应用将要使用的Environment
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
            //3.打印banner
            Banner printedBanner = printBanner(environment);
            //4.根据是否是web项目,来创建不同的ApplicationContext容器
            context = createApplicationContext();
            //5.创建一系列FailureAnalyzer
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            //6.初始化ApplicationContext
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
            //7.调用ApplicationContext的refresh()方法,刷新容器
            refreshContext(context);
            //8.查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行它们。
            afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
            listeners.started(context);
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, listeners, exceptionReporters, ex);
            throw new IllegalStateException(ex);
        }
        listeners.running(context);
        return context;
    }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容