springboot启动的流程图

个人公众号(徐小耳博客)对于springboot,spring,tomcat,netty等框架有更深入的理解,请移步关注

image.png

流程图

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事件

  1. 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事件
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容