开发者

JAVA中SpringBoot启动流程分析

开发者 https://www.devze.com 2023-01-19 10:45 出处:网络 作者: Cuzzz
目录一丶前言二丶SpringBoot启动流程分析1.获取SpringApplicationRunListener实现类,包装成SpringApplicationRunListeners2.SpringApplicationListeners#starting3.prepareEnvironment 根据项目选择Environment实现
目录
  • 一丶前言
  • 二丶SpringBoot启动流程分析
    • 1.获取SpringApplicationRunListener实现类,包装成SpringApplicationRunListeners
    • 2.SpringApplicationListeners#starting
    • 3.prepareEnvironment 根据项目选择Environment实现类,并实例化
    • 4.SpringApplicationListeners#environmentPrepared
    • 5.createApplicationContext
    • 6.prepareContext
      • 6.1从META-INFO/spring.factories中拿所有ApplicationContextInitializer然后回调initialize方法
      • 6.2 将主类包装成BeanDefinition,注册到Spring容器上下文中
    • 7.回调SpringApplicationRunListener#contextLoaded
      • 8.刷新Spring容器上下文
        • 9.回调SpringApplicationRunListener#started
          • 10.callRunners
          • 三丶SpringApplication,ApplicationContext,BeanFactory 三平面

            一丶前言

            在之前我们学习了SpringBoot自动装配如何实现的,我们总结了Spring IOC的底层原理。

            但是我们还是不知道SpringApplication.run(主类.class, args)到底做了哪些事情。本文将和大家一起看看SpringBoot启动的大致流程,探讨SpringBoot留给我们的扩展接口

            二丶SpringBoot启动流程分析

            JAVA中SpringBoot启动流程分析

            上面是SpringBoot调用SpringApplication.run(主类.class, args)启动的源码,源码并不复杂,整体流程大概如下

            JAVA中SpringBoot启动流程分析

            下面我们依据此图,看看这些步骤SpringBoot底层源码

            1.获取SpringApplicationRunListener实现类,包装成SpringApplicationRunListeners

            JAVA中SpringBoot启动流程分析

            SpringApplicationRunListener是SpringBoot框架中的监听器,在SpringBoot启动到达对应阶段的时候,会回调starting,started等方法。

            为什么SpringBoot不适应Spring 里面的ApplicationListener昵,因为ApplicationListener依赖于Spring容器,@EventListener注解需要EventListenerMethodProcessor这个BeanFactoryPostProcessor扫描,将对应的bean和方法包装成ApplicationListener注册到ApplicationContext中(最终注册到ApplicationEventMulticaster事件多播器中)对于ApplicationListener类型bean则直接走注册到Applicatio编程nContext的流程,整个流程只有Spring 容器启动后才能进行,如果没有SpringApplicationRunListener则开发者无法在SpringBoot启动对应阶段进行一些扩展逻辑的回调。

            SpringApplicationRunListeners 可以看成是SpringA编程客栈pplicationRunListener的门面(门面设计模式)

            其使用List<SpringApplicationRunListener>持有所有的SpringApplicationRunListener,然后starting等方法都是循环调用,集合中SpringApplicationRunListener对应的方法

            JAVA中SpringBoot启动流程分析

            JAVA中SpringBoot启动流程分析

            SpringBoot如何获取所有的SpringApplciationListener

            JAVA中SpringBoot启动流程分析

            这里将从META-INF/spring.factories获取org.springframework.boot.SpringApplicationRunListener 定义的实现类全限定类名,然后反射调用构造方法(SpringApplication application, String[] args)进行实例化。随后将根据@Order 或者 Ordered接口定义的顺序进行排序,然后包装成SpringApplicationRunListeners

            JAVA中SpringBoot启动流程分析

            注意无法使用@Component注解 标注在SpringApplciationListener注解上,来实现事件的监听,必须在META-INF/spring.factories中定义,并且必须具备构造方法(SpringApplication application, String[] args)

            EventPublishingRunListener

            JAVA中SpringBoot启动流程分析

            SpringApplication#addListeners 允许我们注册ApplicationListener到SpringBoot中,然后EventPublishingRunListener其内部会new 一个简单的事件多播器SimpleApplicationEventMulticaster,在对应的SpringBoot启动阶段,推送事件。下面式如何注册ApplicationListener

            JAVA中SpringBoot启动流程分析

            注意这些ApplicationListener不会被注册到Spring上下文中,意味着不会响应Spring上下文推送的事件,除非这个ApplicWrgzGationListener是一个Spring Bean 并且被Spring管理。

            下图是EventPublishingRunListener在SpringBoot启动的不同阶段,推送事件

            JAVA中SpringBoot启动流程分析

            2.SpringApplicationListeners#starting

            JAVA中SpringBoot启动流程分析

            没啥好说的,循环回调SpringApplicationRunListener#starting方法

            3.prepareEnvironment 根据项目选择Environment实现类,并实开发者_C培训例化

            在这一步,SpringBoot会根据类路径中的类选择一个Environment并实例化,并且根据当前激活的配置,选择对应的配置文件,进行解析,并保存到Environment中。下面是SpringBoot选择Environment的源码

            JAVA中SpringBoot启动流程分析

            那么SpringBoot是如何判断当前项目是什么应用类型昵?

            其实根据类路径下是否具备指定的类,然后得到指定类型,一般我们都是servlet应用,会选择StandardServletEnvironment

            JAVA中SpringBoot启动流程分析

            4.SpringApplicationListeners#environmentPrepared

            2.SpringApplicationListeners#starting

            5.createApplicationContext

            根据类路径指定类推断使用什么ConfigurableApplicationContext(一般servlet应用使用AnnotationConfigServletWebServerApplicationContext)然后实例化AnnotationConfigServletWebServerApplicationContext

            AnnotationConfigServletWebServerApplicationContext#onRefresh方法在Spring容器刷新后会被调用,这个方法将启动Tomcat内嵌服务器

            6.prepareContext

            这个方法主要会做以下操作

            回调ApplicationContextInitializer#initialize 回调所有SpringApplicationRunListener#contextPrepared 将主类包装成BeanDefinition,注册到Spring容器上下文中 回调所有SpringApplicationRunListener#contextLoaded

            利用SpringApplicationRunListeners回调SpringApplicationRunListener,同2,不在赘述

            6.1从META-INFO/spring.factories中拿所有ApplicationContextInitializer然后回调initialize方法

            JAVA中SpringBoot启动流程分析

            在spring上下文refresh方法调用前,会回调initialize方法

            JAVA中SpringBoot启动流程分析

            这里调用前还会判断ApplicationContextInitializer定义的泛型,保证5这一步创建的上下文,符合泛型的要求

            6.2 将编程客栈主类包装成BeanDefinition,注册到Spring容器上下文中

            这一步非常重要,主类上的注解@SpringBootApplication需要ConfigurationClassPostProcessor解析,才能发挥@Import,@ComponentScan的作用,想要ConfigurationClassPostProcessor处理主类的前提是主类的BeanDefinition需要在Spring容器中。

            也就是说SpringBoot的自动装配,和扫描包路径下的Spring 组件的前提是,主类的BeanDefinition在Spring容器中

            JAVA中SpringBoot启动流程分析

            这里的BeanDefinitionRegistry,其实就是来自5这一步的ApplicationContext,一般来说AnnotationConfigServletWebServerApplicationContext内部持有了一个DefaultListableBeanFactory,DefaultListableBeanFactoryBeanDefinitionRegistry的实现类,其底层使用一个ConcurrentHashMap维护,key是bean的名称,value是对应的BeanDefinition

            JAVA中SpringBoot启动流程分析

            当资源是一个Class的时候,会使用AnnotatedBeanDefinitionReader读取Class对象,生成BeanDefinition

            这一步还支持XML的方式

            7.回调SpringApplicationRunListener#contextLoaded

            同2

            8.刷新Spring容器上下文

            《Spring源码学习笔记12——总结篇IOC,Bean的生命周期,三大扩展点》这篇博客做了详细的分析

            这里会进行自动装配和包路径扫描注册BeanDefinition,然后实例化单例bean

            android

            9.回调SpringApplicationRunListener#started

            同2

            10.callRunners

            从spring容器中拿到ApplicationRunner,和CommandLineRunner调用run方法

            JAVA中SpringBoot启动流程分析

            三丶SpringApplication,ApplicationContext,BeanFactory 三平面

            我们将SpringApplication看作是SpringBoot平面,ApplicationContext看作是Spring平面,BeanFactory看作是Bean工厂平面,SpringBoot启动到触发spring容器刷新,然后触发BeanFactory实例化所有单例,非懒加载bean的流程如下

            JAVA中SpringBoot启动流程分析

            到此这篇关于Java中SpringBoot启动流程分析的文章就介绍到这了,更多相关JAVA中SpringBoot启动流程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

            0

            精彩评论

            暂无评论...
            验证码 换一张
            取 消