Springboot(以1.5.21版本为例)项目中,项目启动除了jvm的经典过程外,以下是Spring boot项目启动过程:
- org.springframework.boot.loader.JarLauncher中的main函数即为上一步jvm加载并执行的函数
- 编写有SpringApplication的应用主函数为其中的启动一个环节
接下来跟下Spring boot启动过程【org.springframework.boot.loader.JarLauncher】:
- registerUrlProtocolHandler,将SystemProperties的“java.protocol.handler.pkgs”设置为:“自定义路径”+|+“org.springframework.boot.loader”【ftp\http\jar...】
- createClassLoader,将BOOT-INF下的lib(三方jar包)和classes(项目已编译二进制文件)路径作为classLoader(LaunchedURLClassLoader)初始化路径,并初始化
- getMainClass,获取manifest下的startClass,即应用项目中的主函数
- 将currentThread中ContextClassloader设置为上一步的LaunchedURLClassLoader
- 创建MainMethodRunner,使用上述classloader进行mainClass的加载,并基于反射执行该mainClass的main函数
继续,进入我们的main函数,我们一般的处理如下:
|
进入Spring boot初始化过程【org.springframework.boot.SpringApplication】:
- initialize(ExampleApplication.class)
- sources中加入ExampleApplication.class
- 判断是否存在"javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext"这两个类【prepareEnvironment步骤中创建和配置environment】
- setInitializers,加载所有类型为org.springframework.context.ApplicationContextInitializer的类,主要作用是作为初始化Spring的回调接口【prepareContext步骤中触发初始化】
- setListeners,加载所有类型为org.springframework.context.ApplicationListener的类,主要是Application事件监听,用于启动后过程触发【prepareContext最后步骤中触发回调】
- run
- 设置SystemProperties:java.awt.headless=“true”(即不需要显示设备、键盘或鼠标)
- 找到所有的org.springframework.boot.SpringApplicationRunListener,并进行初始发布(默认是发布org.springframework.boot.context.event.ApplicationStartedEvent的事件)
- prepareEnvironment,准备环境
- 创建org.springframework.core.env.ConfigurableEnvironment实例,并设置属性源和activeProfile设置(未真正获取这些属性源的值)
- 发布org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent的事件
- createApplicationContext,创建应用上下文
- 依据1.b判断结果选择实际的上下文类型(true:AnnotationConfigEmbeddedWebApplicationContext,false:AnnotationConfigApplicationContext)
- prepareContext,准备处理context上下文
- context.setEnvironment(environment)
- postProcessApplicationContext,context后置处理,
- 在BeanFactory中注册name为“org.springframework.context.annotation.internalConfigurationBeanNameGenerator”的单例beanNameGenerator
- 设置loader,若context类型为GenericApplicationContext->setResourceLoader,若context为DefaultResourceLoader→setClassLoader
- applyInitializers,触发1.c步骤中的所有初始化器【此处boot和cloud会有不同的使用,2.f.v步骤会进行触发】
- 发布空的事件
- 将1.a步骤中的source加入到一个BeanDefinitionLoader(boot),依据的仍是context的BeanDefinitionRegistry,主要是看这些source是否需要作为bean加入到Spring的context中去
- 发布org.springframework.boot.context.event.ApplicationPreparedEvent的事件
- refreshContext,刷新上下文【进入Spring的核心加载过程】
- prepareRefresh,准备刷新上下文
- initPropertySources,初始化属性源及env、SystemProperties等,即将所有的key-value均进行实例化
- validateRequiredProperties,校验必须存在的属性【暂时未找到在哪儿能配置】
- obtainFreshBeanFactory,获取新的beanFactory
- refreshBeanFactory,清除旧的beanFactory,生成新的beanFactory,并进行相应初始化操作【两个子类:org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory,org.springframework.context.support.GenericApplicationContext#refreshBeanFactory,待总结Context类图】
- customizeBeanFactory,设置是否允许beanDefinition被覆盖和是否允许循环引用
- loadBeanDefinitions,加载beanDefinition(bean的定义)到beanFactory中去【org.springframework.web.context.support.AnnotationConfigWebApplicationContext#loadBeanDefinitions,还有其他的,TODO】
- 创建AnnotatedBeanDefinitionReader(class或xml形式编写的bean,以下简称reader)和ClassPathBeanDefinitionScanner(package path方式,以下简称scanner)为该beanFactory进行beanDefinitions的注册
- reader扫描所有当前的已加入的class,scanner扫描所有的basePackages,均将其beanDefinitions进行注册
- 获取所有的resource的位置(XML bean definition文件),并先后用reader和scanner进行尝试找到beanDefinition
- 返回该beanFactory
- refreshBeanFactory,清除旧的beanFactory,生成新的beanFactory,并进行相应初始化操作【两个子类:org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory,org.springframework.context.support.GenericApplicationContext#refreshBeanFactory,待总结Context类图】
- prepareBeanFactory,配置factory的标准上下文特征,比如context的类加载器和后置处理器
- 配置classloader
- 配置后置处理器-postProcessor(ApplicationContextAwareProcessor,ApplicationListenerDetector【若存在loadTimeWeaver的bean,LoadTimeWeaverAwareProcessor】)
- 设置忽略检查依赖的接口(EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware)
- 设置几个默认的bean(BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext)
- postProcessBeanFactory,让实际的context类型进行后期的beanFactory处理
- 列出几个子类:
- org.springframework.web.context.support.AbstractRefreshableWebApplicationContext#postProcessBeanFactory
- 配置bean后置处理器-postProcessor(ServletContextAwareProcessor)
- 设置忽略检查依赖的接口(ServletContextAware,ServletConfigAware)
- org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#postProcessBeanFactory
- 调用:org.springframework.boot.context.embedded.EmbeddedWebApplicationContext#postProcessBeanFactory
- 配置bean后置处理器-postProcessor(WebApplicationContextServletContextAwareProcessor)
- 设置忽略检查依赖的接口(ServletContextAware)
-
registerWebApplicationScopes
- basePackages和annotatedClasses不为空,则进行scan和register
- 调用:org.springframework.boot.context.embedded.EmbeddedWebApplicationContext#postProcessBeanFactory
- org.springframework.web.context.support.GenericWebApplicationContext#postProcessBeanFactory
- 配置bean后置处理器-postProcessor(ServletContextAwareProcessor)
- 设置忽略检查依赖的接口(ServletContextAware)
- web场景针对性处理:WebApplicationContextUtils.registerWebApplicationScopes,WebApplicationContextUtils.registerEnvironmentBeans
- org.springframework.jca.context.ResourceAdapterApplicationContext#postProcessBeanFactory
- 配置bean后置处理器-postProcessor(BootstrapContextAwareProcessor)
- 设置忽略检查依赖的接口(BootstrapContextAware)
- 设置几个默认的bean(BootstrapContext,WorkManager)
- org.springframework.web.context.support.StaticWebApplicationContext#postProcessBeanFactory
- 配置bean后置处理器-postProcessor(ServletContextAwareProcessor)
- 设置忽略检查依赖的接口(ServletContextAware,ServletConfigAware)
- web场景针对性处理:WebApplicationContextUtils.registerWebApplicationScopes,WebApplicationContextUtils.registerEnvironmentBeans
- org.springframework.web.context.support.AbstractRefreshableWebApplicationContext#postProcessBeanFactory
- 列出几个子类:
- invokeBeanFactoryPostProcessors,调用context中注册为bean的beanFactory(注意不是上一步的bean)的postProcesser
- 首先,会找到预先设置的几个【问题来了,什么时候设置的:1.c设置,2.e.iii中部分ApplicationContextInitializer会增加,可能有以下几个:ConfigurationWarningsPostProcessor,CachingMetadataReaderFactoryPostProcessor,PropertySourceOrderingPostProcessor】
- 进入第一步判断
- 如果beanFactory instanceof BeanDefinitionRegistry【此过程会记录哪些已经处理过,第三步会用】
- 拆分为BeanFactoryPostProcessor(List<BeanFactoryPostProcessor> regularList)和BeanDefinitionRegistryPostProcessor(List<BeanDefinitionRegistryPostProcessor> registryList)
- 首先将预设的几个进行拆分
- 然后,主要处理类型为BeanDefinitionRegistryPostProcessor
- 找到的类型为BeanDefinitionRegistryPostProcessor,且继承了PriorityOrdered的postProcesser
- 找到的类型为BeanDefinitionRegistryPostProcessor,且继承了Ordered的postProcesser
- 找到的类型为BeanDefinitionRegistryPostProcessor,且不为上面两步的postProcesser
- 以上三步均做这样几个事
- 排序
- registryList加入这些新找到的postProcessor
- 触发这些新找到的postProcessor
- 最后,处理BeanFactoryPostProcessor,并全部触发
- 如果不是,仅触发这几个预设postProcessor即可
- 如果beanFactory instanceof BeanDefinitionRegistry【此过程会记录哪些已经处理过,第三步会用】
- 接下来,需要找到BeanFactoryPostProcessor类型的其他bean进行触发
- 跳过上一步已经处理过的
- 找到继承了PriorityOrdered的postProcesser
- 找到继承了Ordered的postProcesser
- 找到不为上面两步的postProcesser
- 以上三步均做这样几个事
- 排序
- 触发
- registerBeanPostProcessors,在factory中注册bean的生成拦截器:BeanPostProcessor(内含before和after)
- 根据类型BeanPostProcessor找到所有的postProcessor
- 找到继承了PriorityOrdered的postProcesser
- 找到继承了Ordered的postProcesser
- 找到不为上面两步的postProcesser
- 以上三步均做这样几个事
- 排序
- 将自己注册到beanFactory中(实际触发在真正的构造过程中)
- initMessageSource,初始化messgeSource
- initApplicationEventMulticaster,初始化事件广播器
- onRefresh,做一些特殊处理
- initThemeSource
- org.springframework.boot.context.embedded.EmbeddedWebApplicationContext#onRefresh会进行内置容器的创建
- registerListeners,将ApplicationListener的监听器名字加到viii步中初始化好的多播器中,并将之前发布的event(前面几步有发布一些事件)使用此多播器进行广播
- finishBeanFactoryInitialization,构造所有非lazy的bean
- 初始化context的转换服务 (???):beanFactory.setConversionService(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)
- beanFactory中注册value 解析器(如PropertyPlaceholderConfigurer)
- 构造LoadTimeWeaverAware,尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器
- 冻结bean definition,允许缓存所有的bean 定义的元数据,不期待进一步的更改
- preInstantiateSingletons,构造所有的bean
- 触发构造bean过程(有点绕,不过没有特别的过程,就是会触发beanPostProcessor)
- 触发类型为SmartInitializingSingleton的bean的后置处理【spring boot也有很多bean实现】
- finishRefresh,最后一步
- initLifecycleProcessor,初始化lifecycle处理器
- getLifecycleProcessor().onRefresh(),开启所有类型为org.springframework.context.Lifecycle的bean,执行其start方法
- 发布ContextRefreshedEvent的事件
- registerApplicationContext,如果系统属性中设置了“spring.liveBeansView.mbeanDomain”,那么将当前Application信息加入到context中去(没看懂还是,不过没什么特殊处理)
- prepareRefresh,准备刷新上下文
- afterRefresh,调用所有的ApplicationRunner和CommandLineRunner
- listeners.finished,SpringApplicationRunListener监听结束
- 目前仅一个该监听,发布ApplicationReadyEvent(成功)或ApplicationFailedEvent(失败)事件
至此,Spring boot的基础启动过程分析完毕,其中的可自定义点也基本明了。
以上加粗位置为spring/springboot留出的可扩展点,基于此进行相应扩展即可