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的一个重要工具类.