(1.2)BeanFactory的对象注册与依赖绑定方式

来源:互联网 发布:伯罗奔尼撒战争 知乎 编辑:程序博客网 时间:2024/04/30 11:16

BeanFactory的对象注册与依赖绑定方式

BeanFactory作为一个IoC Service Provider,为了能够明确管理各个业务对象以及业务对象之间的依赖绑定关系,同样需要某种途径来记录和管理这些信息。上一章在介绍IoC Service Provider时,我们提到通常会有三种方式来管理这些信息。而BeanFactory几乎支持所有这些方式,很令人兴奋,不是吗?

 一,直接编码方式

其实,把编码方式单独提出来称作一种方式并不十分恰当。因为不管什么方式,最终都需要编码才能"落实"所有信息并付诸使用。不过,通过这些代码,起码可以让我们更加清楚BeanFactory在底层是如何运作的。

下面来看一下我们的FX新闻系统相关类是如何注册并绑定的(见代码清单4-4)。

代码清单4-4 通过编码方式使用BeanFactory实现FX新闻相关类的注册及绑定

 

 

BeanFactory只是一个接口,我们最终需要一个该接口的实现来进行实际的Bean的管理,Default- ListableBeanFactory就是这么一个比较通用的BeanFactory实现类。DefaultListableBean- Factory除了间接地实现了BeanFactory接口,还实现了BeanDefinitionRegistry接口,该接口才是在BeanFactory的实现中担当Bean注册管理的角色。基本上,BeanFactory接口只定义如何访问容器内管理的Bean的方法,各个BeanFactory的具体实现类负责具体Bean的注册以及管理工作。BeanDefinitionRegistry接口定义抽象了Bean的注册逻辑。通常情况下,具体的BeanFactory实现类会实现这个接口来管理Bean的注册。它们之间的关系如图4-3所示。

 (点击查看大图)图4-3 BeanFactory、BeanDefinitionRegistry
以及DefaultListableBeanFactory的关系

打个比方说,BeanDefinitionRegistry就像图书馆的书架,所有的书是放在书架上的。虽然你还书或者借书都是跟图书馆(也就是BeanFactory,或许BookFactory可能更好些)打交道,但书架才是图书馆存放各类图书的地方。所以,书架相对于图书馆来说,就是它的"BookDefinitionRegistry"。

每一个受管的对象,在容器中都会有一个BeanDefinition的实例(instance)与之相对应,该BeanDefinition的实例负责保存对象的所有必要信息,包括其对应的对象的class类型、是否是抽象类、构造方法参数以及其他属性等。当客户端向BeanFactory请求相应对象的时候,BeanFactory会通过这些信息为客户端返回一个完备可用的对象实例。RootBeanDefinition和ChildBean- Definition是BeanDefinition的两个主要实现类。

现在,我们再来看这段绑定代码,应该就有"柳暗花明"的感觉了。

在main方法中,首先构造一个DefaultListableBeanFactory作为BeanDefinition- Registry,然后将其交给bindViaCode方法进行具体的对象注册和相关依赖管理,然后通过bindViaCode返回的BeanFactory取得需要的对象,最后执行相应逻辑。在我们的实例里,当然就是取得FXNewsProvider进行新闻的处理。

在bindViaCode方法中,首先针对相应的业务对象构造与其相对应的BeanDefinition,使用了RootBeanDefinition作为BeanDefinition的实现类。构造完成后,将这些BeanDefinition注册到通过方法参数传进来的BeanDefinitionRegistry中。之后,因为我们的FXNewsProvider是采用的构造方法注入,所以,需要通过ConstructorArgument- Values为其注入相关依赖。在这里为了同时说明setter方法注入,也同时展示了在Spring中如何使用代码实现setter方法注入。如果要运行这段代码,需要把setter方法注入部分的4行代码注释掉。最后,以BeanFactory的形式返回已经注册并绑定了所有相关业务对象的BeanDefini- tionRegistry实例。

小心 最后一行的强制类型转换是有特定场景的。因为传入的DefaultListableBeanFactory同时实现了BeanFactory和BeanDefinitionRegistry接口,所以,这样做强制类型转换不会出现问题。但需要注意的是,单纯的BeanDefinitionRegistry是无法强制转换到BeanFactory类型的!