1 Spring内部工作机制
ApplicationContext的默认实现是AbstractApplicationContext,可以通过refresh()窥探Spring在刷新时的动作
// 初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
……
//调用工厂后处理器
invokeBeanFactoryPostProcessors(beanFactory);
//注册Bean后处理器
registerBeanPostProcessors(beanFactory);
//初始化消息源
initMessageSource();
//初始化应用上下文事件广播器
initApplicationEventMulticaster();
//初始化其他特殊的Bean.eg由自类实现的Bean
onRefresh();
//注册事件监听器
registerListeners();
//初始化所有单例Bean,懒加载模式的Bean除外
finishBeanFactoryInitialization(beanFactory);
// 完成刷新并发布容器刷新事件
finishRefresh();
1.初始化BeanFactory:调用refreshBeanFactory()刷新BeanFactory,之后调用getBeanFactory()获得BranFactory,这两个方法都是由具体子类实现。这一步中最重要的就是Spring将形成BeanDefinitionRegistry(Bean定义注册表),但是此时的Bean都没有被初始化
2.调用工厂后处理器:在Bean定义注册表中找出工厂后处理器(BeanFactoryPostProcessor子类)并调用对象的接口方法(postProcessBeanFactory())
3.注册Bean 后处理器:在Bean定义注册表中找出Bean 后处理器(BeanPostProcessor子类)并注册到Bean后处理器注册表中
4.初始化消息源:初始化容器的国际化消息资源
5.初始化应用上下文事件广播器
6.初始化其他特使的Bean
7.注册事件监听器,方便响应容器事件
8.初始化所有单实例Bean:初始化所有的单实例Bean并形成Bean的缓存池
9.完成并发布容器刷新事件:应用上下文事件广播器会将该事件广播到每个注册的事件监听器中。
2 Spring IOC流程图
1.ResourceLoader加载bean配置文件并使用对应的Resource表示
2.BeanDefinitionReader读取Resource表示的资源并解析,将配置的Bean表示为BeanDefinition并形成BeanDefinitionRegistry。bean注册表中的Bean是最原始的Bean即没有经过任何处理的Bean。eg符号替换
3.扫描BeanDefinitionRegistry。分为两个主要的步骤
3.1 扫描BeanDefinitionRegistry识别BeanFactoryPostProcessor子类即工厂后处理器。采用工厂后处理器对Bean进行处理,对使用占位符的<bean>标签进行解析并获得配置值即占位符替换
3.2 扫描BeanDefinitionRegistry识别PropertyEditor子类即属性编辑器并形成PropertyEditorRegistry(属性编辑器注册表)
4.从BeanDefinitionRegistry中获取加工后的BeanDefinition并调用InstantiationStrategy进行Bean实例化动作
5.BeanWrepper结合BeanDefinition以及PropertyEditorRegistry中注册的属性编辑器完成属性注入动作
6.利用注册的Bean后处理器对已经完成属性设置的Bean进行后续处理,直接装配出一个准备就绪的Bean
3 BeanDefinition
BeanDefinition是Bean定义在Spring中的内部表示。
RootBeanDefinition是最常用的实现类。它对应一般性的<bean>元素标签。由于Bean存在父子关系,所以RootBeanDefinition表示父Bean,ChildBeanDefinition表示子Bean。没有父Bean的Bean也表示为RootBeanDefinition。
一般情况下BeanDefinition只在容器启动时加载并解析,除非容器刷新或者重启否则这些信息不会发生变化。
BeanDefinition的创建主要包含两个步骤。
1.利用BeanDefinitionReader读取Resource,通过解析Xml并生成DOM对象,该步仅仅是生成<bean>标签对应的Beandefinition对象,形成的Bean是半成品,占位符在该步中并没有被替换
2.利用容器中注册的BeanFactoryPostProcessor对半成品的BeanDefinition进行处理,将占位符替换成实际值。此时的Bean是成品的Bean
4 InstantiationStrategy
实例化策略负责根据BeanDefinition对象创建一个Bean实例。
SimpleInstantiationStrategy是最常用的实例化策略。该策略利用Bean的构造函数或者工厂方法创建Bean实例
CglibSubclassingInstantiationStrategy扩展了SimpleInstantiationStrategy,为进行方法注入的Bean提供了支持。利用Cglib为Bean动态生成子类。在子类中生成方法注入的逻辑,然后利用子类创建Bean的实例
InstantiationStrategy仅仅负责Bean的实例化,相当于new的功能,不会参与Bean属性的设置。我们可以获得此时的Bean实例,但是没有办法使用,因为Bean没有被初始化,Bean的初始化需要BeanWrapper来完成
5 BeanWrapper
完成Bean属性的填充工作。实例创建完成后,通过BeanWrapper将实例包装。
PropertyAccessor接口定义了访问Bean属性的方法。eg:setPropertyValue(String,Object),setPropertyValues(PropertyValues pvs);PropertyEditorRegistry是属性编辑器注册表。从类图结构上可以看出WrapperImpl有3中身份
1.对Bean进行包装即Bean包装器,Wrapper.setWrappedInstance(Object obj)完成Bean的包装
2.实现PropertyAccessor接口,可以访问Bean的属性即属性访问器
3.实现了属性编辑器注册表接口,指定了将外部数据如何转换为Bean属性的规则
可以看出BeanWrapperImpl内部封装可两类组件:1.待处理的Bean,可以直接从BeanDefinitionRegistry获取。2.一套用于设置Bean属性的属性编辑器,从BeanDefinition中获取PropertyValue并通过属性编辑器对PropertyValue进行处理获得Bean属性值并注入