Refresh
ApplicationContext refresh的流程概述
ApplicationContext是spring中的核心容器,refresh是ApplicationContext的一个方法,主要作用是用来初始化ApplicationContext。
refresh一共分为十二个步骤。所有的ApplicationContext有一个共同的父类叫AbstractApplicationContext。这个父类里有refresh方法,这个方法里面有12个比较重要的方法。
![image-20220324171011912](https://pic-bed-1303913583.cos.ap-nanjing.myqcloud.com/img/image-20220324171011912.png)
1、蓝色:代表做一些准备工作。
2—6、绿色:创建并准备BeanFactory对象。
为什么需要BeanFactory对象呢?
因为ApplicationContext只是一个外部容器,核心功能还需要交给BeanFactory来完成。(Bean的创建、Bean的依赖注入、Bean的初始化)
7—12、黄色:准备我们的ApplicationContext,为ApplicationContext里面一些特有的功能做一些准备。
11、红色:比较重要,是在创建和初始化我们的单例对象。容器当中的单例对象都是在第11步创建并初始化完成的。
1、prepareRefresh
要点
●这一步创建和准备 了Environment对象
●要理解 Environment对象的作用
●跟我学怎么调试代码
prepareRefresh主要就是准备了一个Environment对象,这个环境对象后续的代码里都会用到。
他就是为我们spring后续运行时提供一些键值信息。
systemProperties:java中的一些键值(java中的默认编码、文件分割符等)
systemEnvironment:提供了操作系统的键值对(java_home、path、classPath等)
自定义:从自定义的properties文件当中的读取到的信息。例如application.properties文件。
即Environment的作用就是管理各种键值信息,将来其他地方可以用到这些信息,例如@Value
总结
- Environment 的作用之一是为后续@Value,值注入时提供键值
@Value怎么获取值并且解析值的过程
我们还需要做进一步解析,解析的时候需要用到Environment(它里面存的是这些键值)
Environment是一个接口,我们使用的时候创建它的实现类即可。
利用Environment获取配置文件中的键值信息
StandardEnvironment只能解析java和系统的键值,我们在配置文件中自定义的键值无法解析到。
解析SpEL表达式
2、obtainFreshBeanFactory
要点
- 这一步获取(或创建) BeanFactory
- 理解BeanFactory的作用
- 理解BeanDefinition的作用
- BeanDefinition从何而来
![image-20220324193938526](https://pic-bed-1303913583.cos.ap-nanjing.myqcloud.com/img/image-20220324193938526.png)
1、ApplicationContext和BeanFactory的关系?
第一步ApplicationContext里面有一个成员变量Environment创建好之后。第二步会获得第二个成员变量BeanFactory(ApplicationContext里面会有一个成员变量为BeanFactory)。ApplicationContext和BeanFactory是一个组合的关系。虽然在继承关系上BeanFactory是父接口,ApplicationContext是子接口,也就是说ApplicationContext扩展了一些BeanFactory的一些功能,但是在实际使用中他俩是组合关系。
ApplicationContext里面的一些功能并没有自己去实现,例如创建Bean,依赖注入、初始化,这些功能还是借助成员变量BeanFactory来完成的。
2、BeanFactory的成员变量进行初始化
BeanFactory要现有一些bean的定义,要先知道这个Bean长什么样子(Bean是单例还是多例,bean的初始化方法是什么,他有哪些属性需要依赖注入。这些信息都是使用BeanDefinition这个类去描述的,而benDefinitionMap就是用来存储所有的BeanDefinition)
总结
- BeanFactory的作用是负责bean的创建、依赖注入和初始化
- BeanDefinition作为bean的设计蓝图,规定了bean的特征,如单例多例、依赖关系、初始销毁方法等
- BeanDefinition 的来源有多种多样,可以是通过xml获得、通过配置类获得、通过组件扫描获得,也可以是编程添加
通过配置类获取BeanDefinition
通过Bean工厂的后置处理器去解析定义的配置类。
因为spring的标准功能里是没办法识别加了注解@Bean的方法(spring不能把他识别为一个BeanDefinition),需要后置处理器去解析这些@Bean注解,包括Import,ImportResource注解等,那些注解都需要额外的代码去解析。
Bean工厂的后置处理器,对我们的Bean工厂去做一些功能的增强。可以识别一些注解,将这些注解标记的类也作为BeanDefinition添加到Bean工厂里面去。
扫描指定包下标注了注解的类,将这些类添加到BeanFactory里
总结:BeanFactory就是去创建Bean,但它不是一下子就能把Bean创建出来,需要借助BeanDefinition。ApplicationContext和BeanFactory是组合关系,ApplicationContext在Bean的管理上接住了BeanFactory的功能。
3、prepareBeanFactory
要点
- 完善BeanFactory
- 了解谁来解析SpEL
- 了解谁来执行类型转换
- 了解特殊bean的注入
- 两个内置的BeanPostProcessor的作用
顾名思义就是在准备我们的Bean工厂,因为刚开始的Bean工厂里有很多成员变量没有被初始化。所谓的准备Bean工厂就是将这些成员变量初始化好,才能执行后续的工作。
beanExpressionResolver: 解析SpEL表达式,解析#{}的
propertyEditorRegistrars: 注册一些类型转换器(spring在进行值注入的时候,需要把字符串类型转换为其他类型)
resolvableDependencies: 去管理一些特殊的对象用来进行依赖注入。(大部分Bean都是被放在singletonObjects里去完成依赖注入,但是有些特殊的对象能不能注入,比如我想注入BeanFactory本身,我想注入ApplicationContext本身,这些对象不是一个真正的bean,没有在单例池里面,没有在BeanDefinition里面去定义。但是这些Bean也是可以注入的,那么查询这些特殊Bean的时候不是去singletonObjects,而是去resolvableDependencies里面去查询)
beanPostProcessors: 在Bean创建时,对Bean的功能进行一些扩展,对里面的注解进行一些识别。(spring的标准功能里功能是十分有限的,如果要对bean的创建做各种各样的扩展的话,需要借助beanPostProcessors来完成)。一些beanPostProcessors是在bean的创建过程中,对bean的创建、依赖注入各个阶段做一些功能增强。
4、postProcessBeanFactory
它是一个空实现,留给子类去实现。
ApplicationContext有一大类是web环境下的子类,有一大类是非web环境下的子类。web环境下的子类初始化BeanFactory就需要初始化更多的信息,比如要注册一些新的scope,非web环境下只需要singleton和proportype。但是web环境下还需要request、session这些
是一种模板方法的设计模式,refresh方法得主要脉络都被父类给规定死了,但是有一些可以扩展得方法把它留空,将来有子类去实现。
总结.
- 一般 Web环境的ApplicationContext都要利用它注册新的Scope,完善Web下的BeanFactory
- 体现的是模板方法设计模式
5、invokeBeanFactoryPostProcessors
要点
- 理解beanFactory后处理器的作用
- 掌握常见的beanFactory后处理器
通过后置处理器对bean工厂的另一种扩展方式,第四步把一些功能是留给子类去扩展。
总结
- beanFactory后处理器,充当beanFactory的扩展点,可以用来补充或修改BeanDefinition
- ConfigurationClassPostProcessor -解析@Configuration、@Bean、@lmport、 @PropertySource 等=
- PropertySourcesPlaceHolderConfigurer -替换BeanDefinition中的${}
(正常的BeanFactory是没有解析这些注解的功能的,调用后置处理器ConfigurationClassPostProcessor可以解析他们,同时解析的目的就是为了多加一些BeanDefinition)
BeanFactory有两个扩展点,第一处就是交给子类去扩展,第二处就是交给bean的后置处理器
6、registerBeanPostProcessors
要点
- 理解bean后处理器的作用
- 掌握常见的bean后处理器
Bean工厂的后置处理器是对整个Bean工厂的功能进行增强的,但是registerBeanPostProcessors是bean的后置处理器就不一样了,它是对我们接下来bean的创建过程中做各种功能增强。
如果想要ApplicationContext完成各种各样更多的功能,一般就会在第六步加入更多的bean的后置处理器,这些Bean的后置处理器从哪来呢?都是从beanDefinitionMap去搜索,看看这些beanDefinitionMap中有没有人实现了BeanPostProcessors接口。如果实现了接口他就会识别出来,你是一个特殊的bean,是一个bean后置处理器,会把这样的bena创建出来,创建好之后把它添加到beanPostProcessors集合里面。将来在bean创建的时候就会用到这些后置处理器了。
常见的Bean后置处理器
总结
- bean 后处理器,充当bean的扩展点,可以工作在bean的实例化、依赖注入、初始化阶段
- AutowiredAnnotationBeanPostProcessor功能有:解析@Autowired, @Value 注解
- CommonAnnotationBeanPqstProcessor 功能有:解析@Resource, @PostConstruct, @PreDestroy
- AnnotationAwareAspectJAutoProxyCreator 功能有:为符合切点的目标bean自动创建代理
注意:这一步只是找出来有哪些Bean的后置处理器,将他们加入到beanPostProcessors集合中,但是真正这些后置处理器发挥作用的是在bean的创建过程。(现在只是注册,并没有用到他们)
7、initMessageSource
要点
- 理解MessageSource的作用
- MessageSource 从何而来
前面的2-6都是在不断地完善BeanFactory,第七步是给ApplicationContext的成员变量进行初始化和赋值。第七步就是给Message进行初始化赋值的,他就是一个国际化功能。
总结
- 实现国际化
- 容器中一个名为messageSource的bean,如果没有,则提供空的MessageSource实现
8、initApplicationEventMulticaster
要点
- 理解事件广播器的作用
- 事件广播器从何而来.
- 如何发布事件
![image-20220325202025540](https://pic-bed-1303913583.cos.ap-nanjing.myqcloud.com/img/image-20220325202025540.png)
广播器的作用:收发事件。发事件的就是Multicaster,在spring当中设置一些监听器来收事件。当事件发生了Multicaster发送给各个监听器对象。
来源:和MessageSource一样,它也是先去BeanFactory找,看看beanDefinitionMap里面有没有一个Multicaster,如果有,就把他作为applicationEventMulticaster的实现。如果没有,它会提供一个默认的实现。
Multicaster里面有一个集合,这个集合内部维护了所有的监听器,将来Multicatser发事件的时候就会遍历这个集合,将事件发送给对这个事件感兴趣的监听器。
总结
- 用来发布事件给 监听器
- 可以从容器中找名为applicationEventMulticaster的bean作为事件广播器,若没有,也会新建默认的事件广播器
- 可以调用ApplicationContext.publishEvent(事件对象)来发布事件
9、onRefresh
要点
- 这一步是空实现,留给子类扩展
- 掌握对应的设计模式
总结
- SpringBoot 中的子类可以在这里准备WebServer,即内嵌web容器
- 体现的是模板方法设计模式
10、registerListeners
要点
- 理解事件监听器作用
- 监听器从何而来
- 如何接收事件 .
作用:监听器来接收事件
来源:如果beanDefinitionMap里面的bean实现了ApplicationListerner的接口,在这一步就会把这些bean找出来,将他们加入到Multicaster的集合里。Multicaster发事件的时候就将其发送到监听器集合里。
总结
- 用来接收事件
- 部分监听器是事先编程添加的、另一部分监听器来自容器中的bean、还有-部分来自于@EventListener的解析
- 实现ApplicationListener接口,重写其中onApplicationEvent(E e)方法即可
11、finishBeanFactorylnitialization
要点
- 了解conversionService
- 了解内嵌值解析器
- 单例池- singletonObjects
conversionService:类型转换。
之前的propertyEditorRegistrars就是做类型转换的,为什么还需要conversionService?
因为之前的propertyEditorRegistrars接口功能上不完整,所以又设计了另一套接口。
embeddedValueResolvers:用来解析${}。它相当于又封装了一下,会间接调用Environment。
singletonObjects: 将在fininationMap中的非延迟的单例对象创建出来。(在创建的过程中,beanPostProcessors后置处理器都会派上用场。bean的创建、依赖注入、初始化)
总结
- conversionService也是一 套转换机制,作为对PropertyEditor的补充
- 内嵌值解析器用来解析@Value中的${},借用的是Environment的功能
- 单例池用来缓存所有单例对象,对象的创建都分三个阶段(创建、依赖注入、初始化),每- -阶段都有不同的bean后处理器参与迸来,扩展功能
12、finishRefresh
要点
- 了解lifecycleProcessor
- 它从何而来
- 如何控制lifecycle?
- 发布ContextRefreshed事件
生命周期处理器(lifecycleProcessor):容器当中有很多的bean,他们都有自己独立的生命周期(服务启动,停止),他也是在容器当中去找看有没有对应周期处理器,如果有就用,没有就有一个默认的。
他里面有个start、stop方法,相当于大哥一样,它的start方法一旦执行,其他bean的start也要执行。它的stop一旦执行,其他bean的stop也要执行。
总结
- 用来控制容器内需要生命周期管理的bean
- 如果 容器中有名称为lifecycleProcessor的bean就用它,否则创建默认的生命周期管理器
- 调用context的start,即可触发所有实现LifeCycle接口bean的start
- 调用context的stop,即可触发所有实现LifeCycle接口bean的stop
发布事件标识refresh完成。
refresh12个步骤
- prepareRefresh-做好准备工作(创建Environment对象,为spring后续的运行提供一些键值信息)
- obtainFreshBeanFactory -创建或获取BeanFactory
- prepareBeanFactory -准备BeanFactory(为BeanFactory创建各个成员变量,EL表达式解析器、类型转换器、内置的BeanPostProcessor)
- postProcessBeanFactory- 子类扩展BeanFactory
- invokeBeanFactoryPostProcessors -后处理器扩展BeanFactory(Bean工厂的后置处理器:ConfigurationClassPostProceessors,解析配置类的注解:@Configuration、@Bean等)
- registerBeanPostProcessors -准备Bean后处理器(常见的有三个,一个是解析@Autwired注解,一个是解析@Resource、一个是解析@Aspect,创建代理类的)
- initMessageSource -为ApplicationContext提供国际化功能
- initApplicationEventMulticaster -为ApplicationContext提供事件发布器
- onRefresh- 留给子类扩展
- registerListeners -为ApplicationContext准备监听器
- finishBeanFactorylnitialization -初始化单例Bean,执行Bean后处理器扩展
- finishRefresh- 准备生命周期管理器,发布ContextRefreshed事件
2-6:都是在准备BeanFactory
一个是解析@Autwired注解,一个是解析@Resource、一个是解析@Aspect,创建代理类的)
7. initMessageSource -为ApplicationContext提供国际化功能
8. initApplicationEventMulticaster -为ApplicationContext提供事件发布器
9. onRefresh- 留给子类扩展
10. registerListeners -为ApplicationContext准备监听器
11. finishBeanFactorylnitialization -初始化单例Bean,执行Bean后处理器扩展
12. finishRefresh- 准备生命周期管理器,发布ContextRefreshed事件
2-6:都是在准备BeanFactory
从第7开始:回到ApplicationContext,为它的成员进行赋值