定义:
BeanFactoryPostProcessor:是一个接口,它允许自定义修改应用程序上下文的beanDefiinition
BeanDefinitionRegistryPostProcessor:是一个接口,继承接口BeanFactoryPostProcessor,该接口新增postProcessBeanDefinitionRegistry方法,方法参数是 BeanDefinitionRegistry对象,BeanDefinitionRegistry对象是beanDefiinition的保存中心
BeanPostProcessor:在bean实例化的时候,进行切面处理,在实例化的前执行postProcessBeforeInitialization,在实例化后执行postProcessAfterInitialization
一、SpringApllication实例化,进行初始化操作:
它调用getSpringFactoriesInstances(Bootstrapper.class),在多个应用的META-INF/spring.factories文件下获取,key=Bootstrapper的启动类加载器的包路径,并通过class.forName反射,然后把实例放到集合进行Order排序,设置优先级,返回集合。
但是此处,由于META-INF/spring.factories文件没有key=Bootstrapper的信息,故返回了一个空集合。
getSpringFactoriesInstances(ApplicationContextInitializer.class))的作用:在多个应用的META-INF/spring.factories文件下获取,key=ApplicationContextInitializer初始化器的包路径,并通过class.forName反射,然后把实例放到集合进行Order排序,设置优先级,返回集合,并通过setInitializers对本对象属性initializers(初始化器)进行赋值。 初始化器,在spring容器刷新之前,进行接口回调initialize方法
返回的初始化器如下:
getSpringFactoriesInstances(ApplicationListener.class)的作用:在多个应用的META-INF/spring.factories文件下获取,key=ApplicationListener初始化器的包路径,并通过class.forName反射,然后把实例放到集合进行Order排序,设置优先级,返回集合,并通过setListeners对本对象属性listeners(监听器)进行赋值。
返回的监听器如下:
【1】创建临时上下文
【2】配置系统硬件属性
【3】获取监听器并启动:getRunListeners(args)
在META-INF/spring.factories文件下获取key= SpringApplicationRunListener的类路径获得org.springframework.boot.context.event. EventPublishingRunListener,
并通过class.forName反射实例化返回 instances,然后通过new SpringApplicationRunListeners( log, instances, applicationStartup),把EventPublishingRunListener封装到SpringApplicationRunListeners的List集合里。
SpringApplicationRunListener负责在SpringBoot启动的不同阶段,使用内部ApplicationEventMulticaster来广播不同的SpringApplicationEven事件,传递给前面的ApplicatioinListener监听器实现类。比如,”刷新上下文准备阶段” 完成了,就向各个SpringApplicationListener监听器发布”刷新上下文准备阶段” 事件,让各个监听器此时执行对应的逻辑。
【4】准备容器环境:prepareEnvironment
上下文环境本质上就是环境信息的集合:系统变量、环境变量、JDK环境信息、命令行参数,默认变量,servlet相关配置变量,随机值、JNDI属性值,以及配置文件(比如application.properties)等。
这些环境变量是有优先级的。对这些信息加载进来,封装到environment对象中。
发布事件
具体prepareEnvironment方法:
根据webApplicationType实例化不同的环境类:
SERVLET -> new ApplicationServletEnvironment()
REACTIVE -> new ApplicationReactiveWebEnvironment()
other -> new ApplicationEnvironment()
【5】打印spring的logo
【6】创建上下文和容器:createApplicationContext()
根据webApplicationType实例化不同的上下文ConfigurableApplicationContext实现类:
SERVLET -> new AnnotationConfigServletWebServerApplicationContext()
REACTIVE -> new AnnotationConfigReactiveWebServerApplicationContext()
other ->new AnnotationConfigApplicationContext()
于此同时,因为这几个实现类,继承了GenericApplicationContext,而GenericApplicationContext的构造函数中会创建beanFactory,故子类实例化,父类GenericApplicationContext也会跟着实例化,beanFactory其实际上就是IOC容器,类型为DefaultListableBeanFactory,即上下文中有了一个IOC容器
【7】刷新上下文准备阶段prepareContext
【8】刷新上下文:refreshContext(context)
刷新之前,会在context上下文添加一个ApplicationContextClosedListener监听,就是为了在shutdown的时候,优雅的关闭应用。
刷新的核心代码如下:
beanFactory初始化的值:
- 设置类加载器 :setBeanClassLoader
2.设置Spel表达式的解析器 :setBeanExpressionResolver
3.添加属性编辑器 :addPropertyEditorRegistrar 添加属性编辑器
4.添加Bean后置处理器:addBeanPostProcessor
5.设置忽略指定类的自动装配功能:ignoreDependencyInterface
6.自动装配是,指定对应接口的注入对象(一个接口可有多个对象):registerResolvableDependency
7.设置单例:registerSingleton
1.设置request、session作用域的注入对象
2.设置自动装配时接口注入指定对象
该方法顾名思义,就是调用Bean定义注册后处理器,形参:
currentRegistryProcessors :BeanDefinition注册后处理器集合,就一个ConfigurationClassPostProcessor类处理器
registry:BeanDefinition的注册中心,本质是就是IOC容器里有该注册中心Map
applicationStartup:记录器,用于记录程序执行
该处理器为类型ConfigurationClassPostProcessor,是接口BeanDefinitionRegistryPostProcessor的实现类,如实现类:
CachingMetadataReaderFactoryPostProcessor.postProcessBeanDefinitionRegistry:是把beanDefinition注册到容器中;
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry:是处理有注解的beanDefinition,该方法实现逻辑:
一、在beanDefinition容器中,通过判断是否包含注解@component,拿到启动类
二、通过ConfigurationClassParser.parser解析
1:先解析到@SpringBootApplication,把启动类的beanDefinition封装成SourceClass,被用来更直接检测包含哪些注解的一个类
2:通过递归处理内部类,把有注解的类记录下来
3:解析标注@PropertySource的类,处理类成员的值
4:解析标注@ComponentScan的类,检测到启动类,在启动类所在包及子包进行扫描,直接或间接标注@component的类,都会被扫描到,并把对应类的beanDefinition注册到容器中,然后 递归调用ConfigurationClassParser.parser进行解析。
5:解析标注@Import的类,递归解析自身和父注解的@import,解析到@import.value=ImportBeanDefinitionRegistrar 进行记录;解析到@import.value=ImportSelector进行记录,并通过调用selectImports方法把扫描配置文件META-INF/spring.factories,把里面的类扫描,并检测这类是否有注解,如果有,则也需要 递归调用ConfigurationClassParser.parser进行解析
经过这一系列解析,就通过注解拿到了全部需要实例化注入到IOC容器的类
注册方式: PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, applicationContent);
比如:国际化
1.初始化主题来源ThemeSource
2.构造TomcatServletWebServer,并初始化server的配置,并注入到IOC容器中
拿到容器中的beanDefinition集合,结合bean后置处理器进行实例化,并注入到IOC容器中
1.设置管理bean生命周期的LifecycleProcessor处理器
2.用LifecycleProcessor开始webServerGracefulShutdown、webServerStartStop两个Group 的生命周期管理
3.发布”容器刷新完成”事件
4.为MBeanServer注册LiveBeansView
【9】刷新上下文后操作:afterRefresh,空方法
【10】发布”容器加载完成”事件给监听器:listeners.started
【11】启动Spring的Runner加载容器启动后数据
Original: https://www.cnblogs.com/incognitor/p/16049092.html
Author: 無名之徒
Title: Spring Boot启动流程源码解析
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621524/
转载文章受原作者版权保护。转载请注明原作者出处!