springboot启动时序概要2
2021-06-28 17:03:21 1 举报
第二部分重点介绍了Spring的refresh过程,篇幅有限,对重点阶段画的比较详细,大体都做了说明,相信能够表达清楚
作者其他创作
大纲/内容
register
提示:目前支持的EventListener实现类有:ServletContextAttributeListenerServletRequestListenerServletRequestAttributeListenerHttpSessionAttributeListenerHttpSessionIdListenerHttpSessionListenerServletContextListener
以TomcatServletWebServerFactory为例
ServletWebServerFactory
PostProcessorRegistrationDelegate
MergedBeanDefinitionPostProcessor
排序并依次注册实现了Ordered的处理器
prepareWebApplicationContext
registerBeanPostProcessors
addBeanPostProcessorWebApplicationContextServletContextAwareProcessor处理Servlet特有的*Aware接口处理Servlet特有的Scopes
createRegistrationBean
2
BeanPostProcessor
getBean方法会导致bean被实例化,过早的实例化会导致处理器类无法生效
postProcessBeanFactory
addBeanPostProcessor
ServletContextInitializerBeans
将内部处理器们平移到倒数第二位置,将ApplicationListenerDetector移到末尾
然后按照以下优先级搜寻并分批执行1.实现了PriorityOrdered2.实现了Ordered3.剩余的注意:在执行第三批的时候,必须迭代调用getBeanNamesForType方法,直到没有新的Processer出现为止
ServletContextInitializer
SpringApplication
然后按照以下优先级分批执行1.实现了PriorityOrdered2.实现了Ordered3.剩余的注意:getBean方法采用最晚执行的原则,因为处理器本身也是Bean;尽可能让高优先级的处理器能够处理它和它的依赖
this.themeSource = UiApplicationContextUtils.initThemeSource(this)默认是:ResourceBundleThemeSource
这里是Spring内部扩展点,实现了该接口被视为内部处理器;在方法调用时Bean已经实例化,因此仅允许修改mbd本身的一些属性,无法影响Bean实例化流程;适合提前做一些缓存工作。
ServletContextInitializerBeans.RegistrationBeanAdapter
此阶段的重点工作:底层服务器的生命周期处理,Servlet/过滤器/监听器的动态注入等
tomcat创建和一系列配置动作
onStartup(servletContext)
BeanPostProcessor说明:用于Bean创建过程中的回调处理,很类似拦截器的作用,一般调用链为:getBean->createBean->BeanPostProcessor多个处理器按照添加顺序依次执行
ServletContextInitializer
postProcessBeforeInitialization
initApplicationEventMulticaster
mergeInitializers从以下四处合并1.1个匿名函数实现-调用context.setInitParameter2.创建并加入SessionConfiguringInitializer3.作为入参的callback4.工厂注入的ServletContextInitializer
prepareBeanFactory
3.实例化Servlet/过滤器/监听器等组件,并向底层服务器注册
refresh
获取已注册的BeanPostProcessor
create(tomcat)
1.准备Web容器
StandardServletEnvironment
3
invokeInitMethods根据需要执行Bean的init操作
ConfigurableEnvironment
ServletContext和ApplicationContext双向绑定
第三个参数如果我为true,会引起FactoryBean和工厂方法实例化,否则不知道是否满足Type参数,过早实例化会导致相关处理器无法生效,因为处理器可能还躺在在配置文件中
BeanFactoryPostProcessor
对于SpringBoot应用来说,主要由ConfigurationClassPostProcessor类负责自动配置,组件扫描,它分为配置类解析和注册两个步骤,由于篇幅有限很难画到一张图上,请参阅第三部分
registerSingleton
search and getBean
首先执行明确注册的处理器,选择其中满足接口条件的实例context.beanFactoryPostProcessors
GenericWebApplicationContext
BeanFactory
invokeBeanFactoryPostProcessors
已注册的:org.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessorwebServerFactoryCustomizerBeanPostProcessorerrorPageRegistrarBeanPostProcessorpersistenceExceptionTranslationPostProcessororg.springframework.aop.config.internalAutoProxyCreator
postProcessBeanDefinitionRegistry
1
处理器生效之后,元数据可能会被修改,缓存失效例如:占位符被属性值替换
setBeanExpressionResolver用于EL表达式StandardBeanExpressionResolver
二.将第三方对象适配为ServletContextInitializer对象并注册
sources.replace
ApplicationContext
Servlet/Filter/EventListener
get initializers
如果指定class或者packagePath的方式创建ApplicationContext,会触发register或者scan操作,以完成BeanDefinition的扫描,解析和注册在SpringBoot场景下,这些职责归属于ConfigurationClassPostProcessor,详细处理过程请参见本图第三部分
clearMetadataCache
refresh阶段
创建匿名函数,作为回调
prepareRefresh
提示:在SpringBoot环境下,当前阶段内嵌的Web服务器还没创建,所以实际的代替行为会延迟到onRefresh阶段
create(mergeInitializers) 并注册到tomcat
servletContextservletConfigcontextParameterscontextAttributes
registerSingleton包括:environment/systemProperties/systemEnvironment/applicationStartup
提示:可以向Spring注册一个实现了Lifecycle接口的Bean,该Bean的生命周期会纳入Spring容器,与容器的生命周期保持一致
postProcessMergedBeanDefinition
BeanDefinitionRegistryPostProcessor
remove and add
registerSingleton(messageSource)
InnerCallback
onStartup
RegistrationBean
create
TomcatWebServer
addBeanPostProcessor(ApplicationListenerDetector)通过ApplicationListenerDetector来搜寻和注册实现了ApplicationListener的bean
getWebServer(callback)
initPropertySources
registerBeanDefinition
SpringBoot版本:2.5.0 Spring版本:5.3.7
onRefresh
SpringBoot启动时序概要(第二部分)
处理\bENV中占坑的PropertySource
根据自动配置规则,这里能够拿到服务器工厂类,例如:tomcatServletWebServerFactory
initMessageSource
此阶段的重点工作:为容器添加Bean处理器,Bean处理器可以理解为Bean实例化过程中的拦截器。一些重要特性,比如自动注入都依赖Bean处理器实现
addBeanPostProcessor*Aware接口类型的注入不适用常规方式,而是通过ApplicationContextAwareProcessor来处理
一.注册所有ServletContextInitializer;分为以下几组1.ServletRegistrationBean 注册key:Servlet.class2.FilterRegistrationBean 注册key:Filter.class3.DelegatingFilterProxyRegistrationBean 注册key:Filter.class4.ServletListenerRegistrationBean 注册key:EventListener.class5.剩余的 注册key:ServletContextInitializer.class
postProcessAfterInitialization
DelegatingFilterProxyRegistrationBean 也是实现过滤器注册功能,这是对Spring友好的一种实现,以支持懒加载等特性
ServletWebServerApplicationContext
剩余三个阶段:一、registerListeners 重新发现和注册Spring监听器二、finishBeanFactoryInitialization 剩余Bean实例化1.未标记为懒加载的Bean2.包括FactoryBean说明:在不同阶段都会调用getBean实例化一些对象,及其依赖的Bean,一般是参与框架行为或扩展的对象,除此之外的大部分业务Bean,理论上都是在此统一实例化。三、finishRefresh 收尾阶段 1.准备lifecycleProcessor,确保可以处理周期对象2.发现Lifecycle类型的Bean,调用其start方法3.发布ContextRefreshedEvent事件
已生效的:ApplicationContextAwareProcessor 根据需要注入contextApplicationListenerDetector 探测一个Bean是否实现了ApplicationListener并注册WebApplicationContextServletContextAwareProcessor 根据需要注入Servlet相关contextImportAwareBeanPostProcessor 根据需要注入元数据AnnotationMetadata
依次注册剩余的处理器
initialize
ServletContainerInitializer
AbstractAutowireCapableBeanFactory
createBean流程
目前实现类为以下三个:ServletRegistrationBeanAdapterFilterRegistrationBeanAdapterServletListenerRegistrationBeanAdapter
setServletContext
执行callback
Tomcat
BeanDefinitionRegistry
registerSingleton(applicationEventMulticaster)
2.注册web score和单例
start
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);如果没有提供名为applicationEventMulticaster的bean,则使用上述实现
registerResolvableDependency能够注入的只能是bean,但是会出现依赖容器本身的场景,例如BeanFactory不可能作为bean注册,因此借助此方法
创建对应类型的adapter
第三方库
this.scanner.clearCache()this.closed.set(false);this.active.set(true);
ServletContextPropertySource代替之前的StubPropertySource
createWebServer
这是我个人的总结,非常适合想通过源码来探索SpringBoot特性,或者希望更容易理解源码的人查阅如果对你有所帮助的话,请给我点赞哦
最终通过createBeanInstance方法实例化对象
doCreateBean
ServletContextScope
如果还没有创建,则执行创建逻辑并缓存
this.messageSource = new DelegatingMessageSource()如果没有提供名为messageSource的bean,创建一个empty实现
向servletContext注册组件
根据我画的第一部分流程图可知,目前明确定义的处理器只有两个:1.CachingMetadataReaderFactoryPostProcessor2.ConfigurationWarningsPostProcessor
排序并依次注册实现了PriorityOrdered的处理器
registerScope
BeanPostProcessorChecker作用:在注册处理器的过程期间,如果实例化了一个bean,那么它是无法被所有处理器处理的,因为其他的处理器可能还没生效。或者说这个bean不是top-level的,而是一个野路子出来的Bean。BeanPostProcessorChecker就是针对它打印提示日志
接下来执行postProcessBeanFactory方法1.上面步骤中处理的全部处理器2.context.beanFactoryPostProcessors中满足接口条件的部分
此阶段的重点工作:从不同的来源解析出配置类型的Bean,并极尽所能的支持对Bean定义的增删改;工厂处理器可以理解为容器的拦截器,尤其关注容器中BeanDef的内容,大多实现类是对Bean定义进行扩充
0 条评论
下一页