ApplicationContext是spring中的核心容器,refresh是ApplicationContext的一个方法,主要作用是用来初始化ApplicationContext。
refresh一共分为十二个步骤。所有的ApplicationContext有一个共同的父类叫AbstractApplicationContext。这个父类里有refresh方法,这个方法里面有12个比较重要的方法。
1、蓝色:代表做一些准备工作。
2—6、绿色:创建并准备BeanFactory对象。
为什么需要BeanFactory对象呢?
因为ApplicationContext只是一个外部容器,核心功能还需要交给BeanFactory来完成。(Bean的创建、Bean的依赖注入、Bean的初始化)
7—12、黄色:准备我们的ApplicationContext,为ApplicationContext里面一些特有的功能做一些准备。
11、红色:比较重要,是在创建和初始化我们的单例对象。容器当中的单例对象都是在第11步创建并初始化完成的。
要点
●这一步创建和准备 了Environment对象
●要理解 Environment对象的作用
●跟我学怎么调试代码
prepareRefresh主要就是准备了一个Environment对象,这个环境对象后续的代码里都会用到。
他就是为我们spring后续运行时提供一些键值信息。
systemProperties:java中的一些键值(java中的默认编码、文件分割符等)
systemEnvironment:提供了操作系统的键值对(java_home、path、classPath等)
自定义:从自定义的properties文件当中的读取到的信息。例如application.properties文件。
即Environment的作用就是管理各种键值信息,将来其他地方可以用到这些信息,例如@Value
总结
@Value怎么获取值并且解析值的过程
我们还需要做进一步解析,解析的时候需要用到Environment(它里面存的是这些键值)
Environment是一个接口,我们使用的时候创建它的实现类即可。
利用Environment获取配置文件中的键值信息
StandardEnvironment只能解析java和系统的键值,我们在配置文件中自定义的键值无法解析到。
解析SpEL表达式
要点
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)
总结
通过配置类获取BeanDefinition
通过Bean工厂的后置处理器去解析定义的配置类。
因为spring的标准功能里是没办法识别加了注解@Bean的方法(spring不能把他识别为一个BeanDefinition),需要后置处理器去解析这些@Bean注解,包括Import,ImportResource注解等,那些注解都需要额外的代码去解析。
Bean工厂的后置处理器,对我们的Bean工厂去做一些功能的增强。可以识别一些注解,将这些注解标记的类也作为BeanDefinition添加到Bean工厂里面去。
扫描指定包下标注了注解的类,将这些类添加到BeanFactory里
总结:BeanFactory就是去创建Bean,但它不是一下子就能把Bean创建出来,需要借助BeanDefinition。ApplicationContext和BeanFactory是组合关系,ApplicationContext在Bean的管理上接住了BeanFactory的功能。
要点
顾名思义就是在准备我们的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的创建、依赖注入各个阶段做一些功能增强。
它是一个空实现,留给子类去实现。
ApplicationContext有一大类是web环境下的子类,有一大类是非web环境下的子类。web环境下的子类初始化BeanFactory就需要初始化更多的信息,比如要注册一些新的scope,非web环境下只需要singleton和proportype。但是web环境下还需要request、session这些
是一种模板方法的设计模式,refresh方法得主要脉络都被父类给规定死了,但是有一些可以扩展得方法把它留空,将来有子类去实现。
总结.
要点
通过后置处理器对bean工厂的另一种扩展方式,第四步把一些功能是留给子类去扩展。
总结
(正常的BeanFactory是没有解析这些注解的功能的,调用后置处理器ConfigurationClassPostProcessor可以解析他们,同时解析的目的就是为了多加一些BeanDefinition)
BeanFactory有两个扩展点,第一处就是交给子类去扩展,第二处就是交给bean的后置处理器
要点
Bean工厂的后置处理器是对整个Bean工厂的功能进行增强的,但是registerBeanPostProcessors是bean的后置处理器就不一样了,它是对我们接下来bean的创建过程中做各种功能增强。
如果想要ApplicationContext完成各种各样更多的功能,一般就会在第六步加入更多的bean的后置处理器,这些Bean的后置处理器从哪来呢?都是从beanDefinitionMap去搜索,看看这些beanDefinitionMap中有没有人实现了BeanPostProcessors接口。如果实现了接口他就会识别出来,你是一个特殊的bean,是一个bean后置处理器,会把这样的bena创建出来,创建好之后把它添加到beanPostProcessors集合里面。将来在bean创建的时候就会用到这些后置处理器了。
常见的Bean后置处理器
总结
注意:这一步只是找出来有哪些Bean的后置处理器,将他们加入到beanPostProcessors集合中,但是真正这些后置处理器发挥作用的是在bean的创建过程。(现在只是注册,并没有用到他们)
要点
前面的2-6都是在不断地完善BeanFactory,第七步是给ApplicationContext的成员变量进行初始化和赋值。第七步就是给Message进行初始化赋值的,他就是一个国际化功能。
总结
要点
广播器的作用:收发事件。发事件的就是Multicaster,在spring当中设置一些监听器来收事件。当事件发生了Multicaster发送给各个监听器对象。
来源:和MessageSource一样,它也是先去BeanFactory找,看看beanDefinitionMap里面有没有一个Multicaster,如果有,就把他作为applicationEventMulticaster的实现。如果没有,它会提供一个默认的实现。
Multicaster里面有一个集合,这个集合内部维护了所有的监听器,将来Multicatser发事件的时候就会遍历这个集合,将事件发送给对这个事件感兴趣的监听器。
总结
要点
总结
要点
作用:监听器来接收事件
来源:如果beanDefinitionMap里面的bean实现了ApplicationListerner的接口,在这一步就会把这些bean找出来,将他们加入到Multicaster的集合里。Multicaster发事件的时候就将其发送到监听器集合里。
总结
要点
conversionService:类型转换。
之前的propertyEditorRegistrars就是做类型转换的,为什么还需要conversionService?
因为之前的propertyEditorRegistrars接口功能上不完整,所以又设计了另一套接口。
embeddedValueResolvers:用来解析${}。它相当于又封装了一下,会间接调用Environment。
singletonObjects: 将在fininationMap中的非延迟的单例对象创建出来。(在创建的过程中,beanPostProcessors后置处理器都会派上用场。bean的创建、依赖注入、初始化)
总结
要点
生命周期处理器(lifecycleProcessor):容器当中有很多的bean,他们都有自己独立的生命周期(服务启动,停止),他也是在容器当中去找看有没有对应周期处理器,如果有就用,没有就有一个默认的。
他里面有个start、stop方法,相当于大哥一样,它的start方法一旦执行,其他bean的start也要执行。它的stop一旦执行,其他bean的stop也要执行。
总结
发布事件标识refresh完成。
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,为它的成员进行赋值