去年通过实际框架代码的阅读,以及结合《Spring源码深度解析》和《Spring技术内幕》的阅读,对Spring框架内Bean模块有了一个整体性的认识。对此进行的总结性整理和回顾。
一、Spring IOC容器简述
如果将对象相关合作对象的引用或依赖关系的管理直接有具体对象来完成,这样会导致代码的高度耦合性和可测试下的降低。也就是说如果相关合作的引用的对象直接在某一个具体的对象之中进行硬代码不利于合作对象
之间的耦合。 如果将合作对象的引用或者依赖关系交由第三方组件(也就是Spirng IOC容器)来管理对象合作对象的引用和依赖关系的管理(通过依赖注入实现)。这样维护对象间依赖关系的控制权就转移至框架当中,降
低了对象之间的耦合度(也就是控制反转)。
Spring IOC提供了一个基本的JavaBean容器(可以说是beanDefinitionMap ),通过IOC模式管理依赖关系,并通过依赖注入和AOP切面增强了为JavaBean这样的POJO对象赋予事务管理,生命周期管理等基本功能。
DefaultListableBeanFactory.java
/** Map of bean definition objects, keyed by bean name */ //已经完成注册加载的Bean即容器持有载入的BeanDefinition private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
二、Spring IOC容器的结构
Spring框架针对不同的使用场景提供多个不同的功能各异的容器供用户选择和使用。BeanFacotry是IOC容器的最基本形式,其派生出了不同使用场景下的更加高级的IOC容器。
Spring IOC容器是什么实现的?
BeanFactory接口定义了获取Bean及Bean 的各种属性,提供了最基本的IOC容器的功能,是所有容器的基类。Spring框架根据不同的开发场景分别提供了不同的容器包括ApplicationContext、XmlBeanFactory、
ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext等。
(1)容器的层次结构
1) BeanFactory –>HierarchicalBeanFactory –> ConfigurableBeanFactory
HierarchicalBeanFactory接口继承了BeanFactory之后,增加了getParentBeanFactory()的接口功能,是BeanFactory具备了双亲IOC容器的管理功能
ConfigurableBeanFactory接口主要定义了一些对BeanFactory的配置功能
2)BeanFactory –>AutowireCapableBeanFactory
AutowireCapableBeanFactory 接口扩展BeanFactory接口增强了自动装配的功能
3)BeanFactory -> ListabaleBeanFactory
ListabaleBeanFactory接口扩展BeanFactory接口,提供所有bean 实例的枚举,不再需要客户端通过一个个bean name查找
4)BeanFactory –>HierarchicalBeanFactory –> ConfigurableBeanFactory
–>AutowireCapableBeanFactory
–>ListabaleBeanFactory
–>ConfigurableListableBeanFactory –>DefaultListableBeanFactory ->AbstractAutowireCapableBeanFactory ->AbstractBeanFactory
ConfigurableListableBeanFactory接口:继承了ConfigurableBeanFactory 接口,AutowireCapableBeanFactory接口,ListabaleBeanFactory接口 ,提供了对bean定义的分析和修改的便利方法,同时也提供了对单例的预实例化
DefaultListableBeanFactory接口:
AbstractAutowireCapableBeanFactory接口:
AbstractBeanFactory接口:
5)BeanFactory –>HierarchicalBeanFactory
–>AutowireCapableBeanFactory
–>ListabaleBeanFactory
–>ApplicationContext –>WebApplicationContext
ApplicationContext接口:
WebApplicationContext接口:
6)FileSystemXmlApplicationContext
FileSystemXmlApplicationContext接口:是一个支持XML定义的BeanDefinition的ApplicationContext,并且可以指定以文件形式的BeanDefinition的读入,这些文件可以使用网络路径和URL定义来表示。
7)ClassPathXmlApplicationContext
ClassPathXmlApplicationContext接口:一个从Class路径读取BeanDefinition定义文件的ApplicationContext
(2)容器内部的结构和表示
1)Bean的表示(Bean在容器内的抽象,即Bean标签的表示)
Spring内Bean是如何表示的?
BeanDefinition是对我们所定义的Bean的抽象,Spring框架通过它来管理基于Spring 的应用中的各种对象以及它们之间的相互依赖关系。简单的说BeanDefinition就是对象依赖关系的抽象。
BeanDefinitionHolder接口:持有一个BeanDefinition,并持有该BeanDefinition的所有别名(alias)
AliasDefinition接口:对应于alias标签的
ImportDefintion接口:对应于import标签
在Spring中BeanDefinition存在三种实现:RootBeanDefition、ChildBeanDefition、GenericBeanDefition 三者均继承于AbstractBeanDefition
RootBeanDefition类表示嵌套bean内的父<bean>,而ChildBeanDefition表示子<bean>
2)Bean配置文件的读取(Resource到Document)
3)Bean标签的解析(创建AbstractBeanDefinition)
4)Bean标签的注册
Spring将配置文件内的<bean>转化为容器的内部表示BeanDefiniton后将其注册到BeanDefinitionRegistry
BeanDefinitionRegistry接口:就像是Spring配置信息的内存数据库,主要以map的形式保存,后续操作直接从BeanDefinitionRegistry读取配置信息
5)Bean的初始化和加载
三、容器的实现过程(初始化过程)
BeanFactory bf=new XmlBeanFactory(new ClassPathResource(“test.xml”)); MyBean myBean=(MyBean)bf.getBean(“myBean”);
1、Resource 资源文件的抽象
2、加载配置文件(从Resource到Document)
从指定的配置资源路径(“test.xml”)加载配置文件,并将获取到的文件输入流转换为XML文档格式(即创建Document对象),也就是从根据指定路径的ClassPathResource对象(Resource)加载配置文件并将配
置文件转换为Document对象.
3、解析填充BeanDefinition
把配置文件转换为Document后,就需要从Document中提取各个定义的标签进行解析并将其注册到Spring IOC容器内(即添加到beanDefinitionMap 内)。 需要解析的标签有: bean标签、 alias标签、 import标
签、 beans标签、自定义标签,标签的解析过程也是创建BeanDefinition设置属性值的过程.
(1)bean标签的解析
(2)import标签的解析
(3)alias标签的解析
(4)beans标签的解析
(5)自定义标签的解析:
4、加载Bean
Bean在Spring同一个容器内只会被创建一次,后续再获取bean则直接从单例缓存中尝试获取,如果没有获取到则再次从单例工厂中(singletonFactories)加载。
(1)尝试从缓存中获取
(2)获取单例Bean
5、创建Bean
(待续)
6、容器的功能扩展
(待续)