美文网首页
Spring boot 启动流程

Spring boot 启动流程

作者: Harry小哥哥 | 来源:发表于2020-04-09 15:05 被阅读0次

    流程图

    springboot启动.png

    流程解释

    组装SpringApplication

    1.resourceLoader:设置resourceload

    2.设置primarySources:可以把启动类加载进入spring容器

    3.webApplicationType:判断当前application应该运行在什么环境下

    4.mainApplicationClass:找出main方法启动的class

    执行SpringApplication的run方法

    获取SpringApplicationRunListeners

    1.从META-INF/spring.factories获取SpringApplicationRunListener的集合,并依次调用的SpringApplicationRunListener的starting方法---即最终调用ApplicationListener的onApplicationEvent方法,发布springboot启动事件

    prepareEnvironment(目前profile功能已经被maven取代了)

    1.ConfigurableEnvironment:代表两种意义:一种是profiles,用来描述哪些bean definitions是可用的;一种是properties,用来描述系统的配置,其来源可能是配置文件、JVM属性文件、操作系统环境变量等等

    2.getOrCreateEnvironment():根据webApplicationType创建不同的Environment

    3.configureEnvironment(XX):通过configurePropertySources(environment, args)设置properties,通过configureProfiles(environment, args)设置profiles

    4.listeners.environmentPrepared(environment);发布environmentPrepared事件,即调用ApplicationListener的onApplicationEvent事件

    bindToSpringApplication:即把当前的environment和当前的springApplication绑定

    6.ConfigurationPropertySources.attach(environment):将ConfigurationPropertySource放入environment的propertysource中的第一个

    createApplicationContext:创建spring的容器

    1.根据不同的webApplicationType设置不同的contextClass(容器的class类型),然后生成不同的容器实例对象

    2.生成容器实例的时候,对于Kotlin类使用'primary'构造函数实例化一个类,如果不是就使用默认构造函数,根据得到构造函数生成实例对象,如果构造函数不是公共的,我们尝试去改变并访问

    prepareContext:准备容器,在准备刷新容器前准备好容器

    1.context.setEnvironment(environment):设置spring容器的environment

    2.postProcessApplicationContext(context):设置beanNameGenerator和resourceLoader

    3.applyInitializers(context):调用ApplicationContextInitializer的initialize来初始化context,其中还检测各个ApplicationContextInitializer是否接受该类型的容器

    4.listeners.contextPrepared(context);即调用SpringApplicationRunListener的contextPrepared方法,但目前是个空实现。

    5.分别注册springApplicationArguments和springBootBanner这两个bean

    6.getAllSources就是获取我们的primarySources和sources

    7.load(context, sources.toArray(new Object[0])):首先创建BeanDefinitionLoader,设置该loader的sources,annotatedReader,xmlReader,scanner,以及添加scanner的ExcludeFilter(即过滤springboot的启动类),若用户启动的时候设置了beanNameGenerator,resourceLoader,environment的话就替代我们自身设置的属性。同时根据source的类型选择不同的load方法,这边我们是load(class),最终判断是否是component注解,是的话就通过annotatedReader将启动类注册成bean

    8.listeners.contextLoaded(context):首先判断ApplicationListener是否属于ApplicationContextAware,如果是的话就将spring容器赋值给该listener,然后将该ApplicationListener赋值给spring容器,然后调用ApplicationListener的onApplicationEvent方法

    refreshContext(context):真正的刷新spring容器

    一.refresh(context):

    1.prepareRefresh():设置些初始的操作比如,开启激活,启动日期,初始化propertySource。

    2.获取beanFactory

    3.prepareBeanFactory(beanFactory):设置beanFactory的classloader,BeanExpressionResolver,PropertyEditorRegistrar,ApplicationContextAwareProcessor和忽略xxxxAware,注册依赖,还有ApplicationListenerDetector

    ApplicationContextAwareProcessor:只是将applicationContext传递给ApplicationContextAwareProcessor,方便后面的xxxAware调用

    忽略xxxxAware:忽略这些Aware接口实现类中与接口set方法中入参类型相同的属性的的自动注入这样就保证了关键的类是由spring容器自己产生的而不是我们注入的,

    自动注入不是指的@AutoWire 而是指的是beans的default-autowire="byType" 或在bean的autowire="byType" ,这样spring 回去ioc容器寻找类型相似的类型给其注入,如果实现了spring 的xxaware接口,就不会自动注入记载filterPropertyDescriptorsForDependencyCheck删除与入参类型相同的属性

    注册依赖:即指定一些类自动注入的实例是spring指定的实例对象

    ApplicationListenerDetector:检测实现了ApplicationListener的实现类,因为有些实现类,无法通过getBeanNamesForType获取到。

    4.postProcessBeanFactory(beanFactory):继续设置ignoreDependencyInterface(ServletContextAware)还有annotatedClasses,basePackages如果存在就设置。

    5.invokeBeanFactoryPostProcessors(beanFactory):从beanFactoryPostProcessors获取BeanFactoryPostProcessor,然后先执行BeanDefinitionRegistryPostProcessor类型的postProcessBeanDefinitionRegistry,继续从beanFactory获取BeanDefinitionRegistryPostProcessor类型的bean然后执行postProcessBeanDefinitionRegistry,执行的过程按照PriorityOrdered,Ordered,普通的类型进行执行,然后优先执行registryProcessors的postProcessBeanFactory在执行regularPostProcessors的postProcessBeanFactory,再从BeanFactory获取PriorityOrdered,Ordered,普通的类型三种类型的BeanFactoryPostProcessor,并按照顺序执行。总结:从之前加入的beanFactoryPostProcessor先执行postProcessBeanDefinitionRegistry(假如是BeanDefinitionRegistryPostProcessor)然后在执行postProcessBeanFactory方法,然后从beanFactory获取BeanFactoryPostProcessor 然后执行postProcessBeanFactory,执行过程中都要按照PriorityOrdered,Ordered,普通的类型三种类型的顺序执行。

    6.registerBeanPostProcessors:从beanFactory获取BeanPostProcessor分别按照PriorityOrdered,Ordered,普通的类型注册BeanPostProcessor

    7.BeanPostProcessor和BeanFactoryPostProcessor:前者是对bean初始化前后进行设置,后者可以对beanFactory进行修改 或者,可以对beanDefinition进行修改或者增加或者初始化渴望提前初始化的bean

    8.initMessageSource():一般是我们用来初始化我们国际化文件的

    9.initApplicationEventMulticaster():设置applicationEventMulticaster,spring发布各种事件就依靠他,这个和springboot发布事件使用相同的类

    10.onRefresh():初始化其他的子容器类中的bean,同时创建spring的内置tomcat,这在后期Springboot内嵌式tomcat中详细阐述

    11.registerListeners():添加用户设置applicationListeners,然后从beanFactory获取ApplicationListener,然后发布需要earlyApplicationEvents事件

    12.finishBeanFactoryInitialization(beanFactory):实例化非懒加载的剩余bean

    13.finishRefresh:清理资源缓存,初始化lifecycle,调用lifecycle的onrefresh,发布ContextRefreshedEvent的事件,激活JMX,启动tomcat

    二.context.registerShutdownHook():注册一个线程,该线程主要指向doclose方法,doClose方法的逻辑就是:从applicationContexts集合中删除当前容器,MBeanServer卸载MBean,发布容器关闭事件,调用了实现了lifecycleProcessor接口的bean,destroyBeans,closeBeanFactory,onClose:关闭内置tomcat,active设置为false

    afterRefresh(context, applicationArguments):目前是空的实现

    listeners.started(context):发布started事件

    callRunners(context, applicationArguments)

    1.从spring容器中获取ApplicationRunner和CommandLineRunner对象,然后按照顺序排序,循环调用他们的run方法

    handleRunFailure(context, ex, exceptionReporters, listeners)

    1.处理不同的异常状态,然后调用listeners.failed(context, exception),并关闭spring容器

    listeners.running(context):发布running事件

    相关文章

      网友评论

          本文标题:Spring boot 启动流程

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