7.8.3 容器中的工厂Bean
此处的工厂Bean
,与前面介绍的实例工厂方法创建Bean
,或者静态工厂方法创建Bean
的工厂有所区别:前面那些工厂是标准的工厂模式, Spring
只是负责调用工厂方法来创建Bean
实例;此处的工厂Bean
是Spring
的一种特殊Bean
,这种工厂Bean
必须实现FactoryBean
接口。FactoryBean
接口是工厂Bean
的标准接口,把工厂Bean
(实现FactoryBean
接口的Bean)
部署在容器中之后,如果程序通过getBean()
方法来获取它时,容器返回的不是FactoryBean
实现类的实例,而是返回FactoryBean
的产品(即该工厂Bean
的getObject()
方法的返回值)FactoryBean
接口提供如下三个方法。
FactoryBean 接口方法 |
描述 | ||
---|---|---|---|
T getObject() |
该方法负责返回该工厂Bean 生成的Java 实例。 |
||
Class<?> getObjectType() |
该方法返回该工厂Bean 生成的Java 实例的类型。 |
||
boolean isSingleton() |
该方法用于判断该工厂Bean 生成的Java 实例是否为单例模式。 |
||
配置FactoryBean 与配置普通Bean 的定义没有区别,但当程序向Spring 容器请求获取该Bean 时,容器返回该FactoryBean 的产品,而不是返回该FactoryBean 本身。 |
|||
从上面介绍不难发现,实现FactoryBean 接口的最大作用在于:Spring 容器并不是简单地返回该Bean 的实例,而是返回该Bean 实例的getObject() 方法的返回值,而getObject() 方法则由开发者负责实现,这样开发者希望Spring 返回什么,只要按需求重写getObject() 方法即可。 |
|||
# 程序示例 # | |||
## 项目结构 ## | |||
|
GetFieldFactoryBean.java
下面定义了一个标准的工厂Bean
,这个工厂Bean
实现了FactoryBean
接口。
1 | package org.crazyit.app.factory; |
上面的GetFieldFactoryBean
是一个标准的工厂Bean
,该工厂Bean
的关键代码就在所实现的getObect()
方法,该方法的执行体先使用反射获取targetClass
对应的Class
对象,再获取targetField
对应的类变量的值。 GetFieldFactoryBean
的targetClass
、 targetField
都提供了setter
方法,因此可接受Spring
的设值注入,这样即可让GetFieldFactoryBean
获取指定类的、指定静态Field
的值。
由于程序不需要让GetFieldFactoryBean
的getObject()
方法产生的值是单例的,故该工厂类的isSingleton()
方法返回false
.
下面配置文件将使用GetFieldFactoryBean
来获取指定类的、指定静态Field
的值。
beans.xml
1 |
|
从上面的程序可以看出,部署工厂Bean
与部署普通Bean
其实没有任何区别,同样只需为该Bean
配置id
、 class
两个属性即可,但Spring
对FactoryBean
接口的实现类的处理有所不同。
Spring容器对工厂Bean的处理过程
Spring
容器会自动检测容器中的所有Bean
,如果发现某个Bean
实现类实现了FactoryBean
接口,Spring
容器就会在实例化该Bean
、根据<property>
执行setter
方法之后,额外调用该Bean
的getObject()
方法,并将该方法的返回值作为容器中的Bean
.
下面程序示范了获取容器中的FactoryBean
的产品。
SpringTest.java
1 | package lee; |
上面程序main方法中前两行输出代码,直接请求容器中的FactoryBean
, Spring
将不会返回该FactoryBean
本身,而是返回该FactoryBean
的产品;
程序中的第三行输出代码代码在Bean id
前增加&
符号,这将会让Spring
返回FactoryBean
本身。
测试
编译、运行该程序,可以看到如下输出:
1 | North |
从上面三行输出可以看出,使用该GetFieldFactoryBean
即可让程序自由获取任意类的、任意静态Field
的值。实际上, Spring
框架本身提供了一个FieldRetrievingFactoryBean
,这个FactoryBean
与我们自己实现的GetFieldFactoryBean
具有基本相同的功能,7.10节会详细介绍FieldRetrievingFactoryBean
的功能和用法。
实际上, FactoryBean
是Spring
中非常有用的一个接口, Spring
内置提供了很多实用的工厂Bean
,例如TransactionProxyFactoryBean
等,这个工厂Bean
专门用于为目标Bean
创建事务代理。Spring
提供的工厂Bean
,大多以Factory Bean
后缀结尾,并且大多用于生产一批具有某种特征的Bean
实例,工厂Bean
是Spring
的一个重要工具类.
原文链接: 7.8.3 容器中的工厂Bean