此处的工厂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的一个重要工具类。