1.内部工作机制
Spring的AbstractApplicationContext是ApplicationContext抽象实现类,该抽象类的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程,这些处理过程清晰刻画了Spring容器启动时所执行的各项操作。下面,我们来看一下refresh()内部定义了哪些执行逻辑。
1.初始化BeanFactory:根据配置文件实例化BeanFactory,getBeanFactory()方法由具体的子类实现。在这一步中,Spring将配置文件的信息装入到容器的Bean定义注册表中,但此时Bean还没有初始化;
ConfigurableListableBeanFactory beanFactory=getBeanFactory();//初始化BeanFactory
2.调用工厂后处理器:根据反射机制从BeanDefinitionRegistry中找出所有BeanFactoryPostProcessor类型的Bean,并调用其postProcessBeanFactory()接口方法;
invokeBeanFactoryPostProcessors();//调用工厂后处理器
3.注册Bean后处理器:根据反射机制从BeanDefinitionRegistry中找出所有BeanPostProcessor类型的Bean,并将它们注册到容器Bean后处理器的注册表中;
registerBeanPostProcessors();//注册Bean后处理器
4.初始化消息源:初始化容器的国际化信息资源;
InitMessageSource();
5.初始化应用上下文事件广播器;
InitApplicationEventMulticaster();
6.初始化其他特殊的Bean;
OnRefresh();//初始化其他特殊的Bean;由具体的子类实现
7.注册事件监视器;
registerListeners();
8.初始化所有单实例的Bean,使用懒初始化模式的Bean除外:初始化Bean之后,将它们放入Spring容器的缓存之中;
finishBeanFactoryInitialization(beanFactory);
9.发布上下文刷新事件:创建上下文刷新事件,事件广播器负责将这些事件广播到每一个注册的事件监听器中;
finishRefresh();//完成刷新并发布容器刷新事件
下图就是IoC流水线示意图
2.什么是Bean?什么又是BeanDefinition?
Bean是什么呢?这个其实可以简单的理解为Spring容器管理的类。那么BeanDefinition又是什么呢?也可以简单的理解为它是用来描述bean的,举个栗子:汽车就好比是Bean 汽车有轮子,汽车有颜色的,这就是BeanDefinition。
org.springframework.beans.factory.config.BeanDefinition是配置文件< bean >元素标签在容器中的内部表示。< bean >元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition则提供了相应的beanClass、scope、lazyInit属性。
Spring通过BeanDefinition将配置文件中的< bean >配置信息转换为容器的内部表示,并将这些BeanDefinition注册到BeanDefinitionRegistry中,Spring容器的BeanDefinitionRegistry就像是Spring配置信息的内存数据库,后续操作直接从BeanDefinitionRegistry中读取配置信息。一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或重启,这些信息不会发生变化,当然如果用户有特殊的需求,也可以通过编程的方式在运行期调整BeanDefinition的定义。
我们可以打个比方:Bean相当于汽车,那么Spring就是汽车制造厂。每一辆汽车所拥有的属性:比如颜色啊,型号啊等这些描述是BeanDefinition,当然这些描述都没有特定的信息,比如只说了这个汽车应该有型号,但没说是捷达还是途锐。汽车在制造、入仓、质检、出仓这一过程中需要一张汽车注册表,这张注册表上记录着所有汽车的信息,这张注册表我们就可以看作是BeanDefinitionRegistry。制造厂在后续的操作中将直接从注册表中提取这些汽车的信息,这样更加快捷。
创建最终的BeanDefinition主要包括两个步骤:
1.利用BeanDefinitionReader对配置信息Resource进行读取(对每一辆汽车的应有属性做一个总结,比如 颜色-型号-发动机),简单地为每个< bean >生成对应的BeanDefinition对象(一张临时的表)。当然这里生成的BeanDefinition可能是半成品。这时因为在配置文件中,我们可能通过占位符变量引用外部属性文件的属性,这些占位符变量在这一步还没有被解析出来(比如生产的汽车用了别的厂商的自动变速箱,但我们这个厂子没有生产自动变速箱的能力,所以一开始会不识别这个是什么属性,比如颜色-型号-发动机-未知设备)。
2.利用容器中注册的BeanDefinitionPostProcessor对半成品的BeanDefinition进行加工处理(通过设备采购处主任-这个人采购设备的当然认识自动变速箱,对刚才的临时表进行进一步处理从而生成可供仓库管理使用的汽车生产管理表,比如颜色-型号-发动机-自动变速箱),将以占位符表示的配置解析为最终的实际值,这样半成品的BeanDefinition就为成品的BeanDefinition了。
3.InstantiationStrategy
OK,这个东西很明显是用作实例化Bean对象的。
org.springframework.beans.factory.support.InstantiationStrategy负责根据BeanDefinition对象去创建一个Bean实例(比如:根据汽车生产管理表上的信息,出厂编号001的汽车:颜色-型号-发动机-自动变速箱)。
Spring之所以将实例化Bean的工作通过一个策略接口进行描述,是为了方便可以采用不同的实例化策略,以满足不同的应用需求(你可以流水化生产,也可以VIP手工化定制生产,一切为了客户的需求!)。
InstantiationStrategy仅负责实例化Bean的操作,相当于执行Java语言中new的功能,它并不会参与Bean属性的设置工作(就是只管按照图纸和指标生产)。所以由InstantiationStrategy返回的Bean实例实际上只是一个半成品的Bean实例,属性的填充工作需要交给BeanWrapper完成。
4.BeanWrapper
org.springframework.beans.BeanWrapper是Spring框架中的重要组件类。BeanWrapper相当于一个代理器,Spring通过BeanWrapper完成Bean属性的填充工作。在Bean实例被InstantiationStrategy创建出来之后,容器主控程序将Bean实例通过BeanWrapper包装起来,这是通过调用BeanWrapper#setWrappedInstance(Object obj)方法完成的。
这个时候就应该进行属性填充了:出厂编号001的汽车:黑色-途锐-3.0tv6发动机-采埃孚8AT手自一体变速箱