IoC容器
Spring中有两个主要的容器系列:BeanFactory和ApplicationContext。
BeanFactory: 定义了IoC容器的基本功能。ApplicationContext: 在简单容器的基础上,通过继承MessageSource、ResourceLoader、ApplicationEventPublisher等接口增加了许多面向框架的特性。
Spring通过定义BeanDefinition来管理各种Bean以及它们之间的依赖关系,是对它们的抽象,是IoC容器的核心数据结构。
BeanFactory容器原理
在Spring中默认把DefaultListableBeanFactory作为一个功能完整的IoC容器。

|
|
Spring中使用Resource来封装BeanDefinition的信息源(XML文件),IoC容器通过Resource来定位BeanDefinition的信息,从而完成容器的初始化和依赖注入过程。
通过调用XmlBeanDefinitionReader的loadDefinitions()方法从Resource中开始载入BeanDefinition。
ApplicationContext容器原理
ApplicationContext容器扩展了MessageSource接口,可以支持国际化的实现,开发多语言版本;具体的ApplicationContext实现都是继承了DefaultResourceLoader的子类,可以从不同的地方得到BeanDefinition的资源;同时还继承了ApplicationEventPublisher接口,从而在应用上下文中引入了事件机制,这些事件机制和Bean的生命周期的结合为Bean的管理提供了便利。
ApplicationContext是通过refresh()方法来启动IoC容器的,同时还会对BeanDefinition的信息源进行封装成Resource(例如 ClassPathResource、FileSystemResource等)。
IoC容器的初始化
IoC容器的初始化分为3个过程:
Resource的定位过程,即BeanDefinition的资源定位。BeanDefinition的载入和解析。BeanDefinition在IoC容器中的注册。
XML -> Resource -> Document -> BeanDefinition
Resource定位
使用DefaultListableBeanFactory时,需要自己去定位Resource,并提供相应的BeanDefinitionReader来对这些信息进行处理。DefaultListableFactory是一个纯粹的IoC容器。
而在ApplicationContext中已经提供了一系列Resource定位的实现以及BeanDefinitionReader。
BeanDefinition的载入和解析
IoC容器的载入过程,是把定义的Bean转化成Spring内部表示的数据结构(BeanDefinition)的过程。
BeanDefinition载入分为两部分,首先通过调用XML的解析器得到Document对象,然后通过DocumentReader完成对Document对象的解析(按照Spring的Bean规则,默认是使用DefaultBeanDefinitionDocumentReader)。
在DefaultBeanDefinitionDocumentReader中通过调用BeanDefinitonParserDelegate的processBeanDefinition()方法来实现,处理的结果是生成BeanDefinitionHolder对象持有。BeanDefinitionHolder对象除了持有BeanDefinition对象外,还有其他与BeanDefinition的使用相关的信息,比如 Bean 的名字、别名集合等。
BeanDefinition在IoC容器中的注册
通过对BeanDefinition的载入和解析过程,在IoC容器内已经建立相应的数据结构和数据表示,但是这些数据还不能供IoC容器直接使用,需要对这些BeanDefinition对象进行注册。
IoC容器中通过一个ConcurrentHashMap来保持和维护这些加载的BeanDefinition。
注册完,整个IoC容器的初始化就完成了。
IoC容器的依赖注入
依赖注入的过程是在用户第一次向IoC容器索要 Bean 时触发的,也可以通过设置
lazy-init=false属性让容器完成对 Bean 的预实例化(其实也是一个完成依赖注入的过程)。
触发依赖注入的入口在BeanFactory提供的getBean()方法中。具体的依赖注入发生时在BeanWrapper的实现类BeanWrapperImpl中setPropertyValue()方法中实现。
在Bean的创建和对象依赖注入的过程中,需要根据BeanDefinition中的信息递归的完成。一个递归是在上下文中查找需要的Bean和创建Bean的递归调用。另一个递归是在依赖注入时,通过递归调用容器的getBean()方法,得到当前Bean依赖的Bean,同时也触发对依赖Bean的创建和注入。
Bean的生命周期
Bean实例的创建
为Bean实例设置属性
调用Bean的初始化方法
应用Bean
容器关闭时调用Bean的销毁方法。