7.8.3 容器中的工厂Bean
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()
方法即可。
程序示例
项目结构
1 | E:\workspace_QingLiangJiJavaEEQiYeYingYongShiZhang5\GetFieldFactoryBean |
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
的一个重要工具类.