此处的工厂Bean,与前面介绍的实例工厂方法创建Bean,或者静态工厂方法创建Bean的工厂有所区别:前面那些工厂是标准的工厂模式,Spring只是负责调用工厂方法来创建Bean实例;此处的 工厂Bean 是Spring的一种特殊Bean,这种工厂Bean必须实现FactoryBean接口。
FactoryBean接口是工厂Bean的标准接口,实现该接口的Bean通常只能作为工厂Bean使用,当我们将工厂Bean部署在容器中,并通过getBean( )方法来获取工厂Bean时,容器不会返回FactoryBean实例,而是返回FactoryBean的产品。
FactoryBean接口提供如下三个方法:
Object getObject( ) | 实现该方法负责返回该工厂Bean生成的Java实例。 |
Class getObjectType( ) | 实现该方法返回该工厂Bean生成的Java实例的实现类。 |
boolean isSingleton( ) | 实现该方法表示该工厂Bean生成的Java实例是否为单例模式。 |
Person.java :
public interface Person { public String sayHello(String name); public String sayGoodBye(String name); }Chinese.java :
public class Chinese implements Person{ @Override public String sayGoodBye(String name) { return "再见,"+name; } @Override public String sayHello(String name) { return "你好,"+name; } }PersonFactory.java :
public class PersonFactory implements FactoryBean { private Person p; //返回工厂Bean所生产的产品 public Person getObject(){ if(p==null){ p=new Chinese(); } return p; } //获取工厂Bean所生产的产品的类型 public Class<?> getObjectType() { return Chinese.class; } //返回该工厂Bean所生产的产品是否为单例 public boolean isSingleton() { return true; } }bean.xml核心配置:
<bean id="chinese" class="com.bean.PersonFactory"/>Test.java :
public class Test { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml"); //直接请求FactoryBean时,系统将返回该FactoryBean的产品 Person p1=(Person) ctx.getBean("chinese");//1 System.out.println(p1.sayHello("汤姆")); System.out.println(p1.sayGoodBye("汤姆")); //再次获取该FactoryBean的产品 Person p2=(Person) ctx.getBean("chinese");//2 System.out.println(p1==p2); System.out.println(ctx.getBean("&chinese"));//3 } }运行Test.java,控制台输出:
上面的PersonFactory是一个标准的工厂Bean,该PersonFactory的getObject( )方法保证每次产生的Person对象是单例的,故该工厂类的isSingleton( )方法返回true。
Test.java中1和2直接请求容器中的FactoryBean,Spring将不会返回该FactoryBean实例,而是返回该FactoryBean的产品;程序3在Bean id前增加&符号,这将会让Spring返回FactoryBean本身。
因为FactoryBean以单例方式管理产品Bean,因此两次请求的产品,是同一个共享实例。
当程序需要获取FactoryBean本身时,并不直接请求Bean id,而是在Bean id前增加&符号。
对于初学者而言,可能无法体会到 工厂Bean 的作用。实际上,FactoryBean是Spring中非常有用的一个接口,Spring内置提供了很多实用的工厂Bean,例如TransactionProxyFactoryBean等,这个工厂Bean专门用于为目标Bean创建事务代理。
Spring提供的工厂Bean,大多以FactoryBean后缀结尾,Spring提供的工厂Bean,大多用于生产一批具有某种特征的Bean实例,工厂Bean是Spring的一个重要工具类。