使用过Spring的同学一定对BeanFactory不会陌生,因为Spring其中一个最大的特性就是Bean容器,顾名思义就是用来存放并提供Java Bean的。但是,估计不少人对FactoryBean鲜有耳闻。这两个词看着非常类似,但是概念和功能却截然不同。
我们先重新来看看BeanFactory,从名字我们就可以看出来它其实是一个Bean工厂,通过工厂模式来为我们提供Java Bean的使用。通过BeanFactory的使用,调用者不需要知道Bean的具体创建细节,直接通过BeanID或Bean类型来获取即可,非常便利。所以,我们抓住了本质:BeanFactory是一个工厂类。
那FactoryBean呢?如果还是从名字上分析,那它就是一个Bean?那它和普通的Java Bean又有什么区别呢?首先,我们先确认,它确实就是一个Bean!接下来,我们就来好好分析一下这个所谓的FacoryBean到底有什么神奇之处。我们先来看一段示例代码。
public class FactoryBeanDemo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/factory-bean-demo.xml");
Foo foo = applicationContext.getBean(Foo.class);
foo.hello();
}
}
public class FooFactoryBean implements FactoryBean<Foo> {
@Override
public Foo getObject() throws Exception {
// 这里可以定义更加复杂的对象创建逻辑
return new Foo("I am a Foo instance from FooFactoryBean");
}
@Override
public Class<?> getObjectType() {
return Foo.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
public class Foo {
private String msg;
public Foo(String msg) {
this.msg = msg;
}
public void hello(){
System.out.println(msg);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>
<bean class="com.lmmmowi.java.explore.spring.beans.factory_bean_demo.FooFactoryBean" />
</beans>
以上我们通过三个简单的类编写了一个最基本的FactoryBean的示例Demo。我们可以看到,FactoryBean其实是Spring框架提供的一个接口,而且还是一个泛型接口。这个接口的作用,就是生成一个Java Bean。至于生成Java Bean的具体逻辑,则需要我们自己编写类并实现该接口。这个接口有三个方法:
- T getObject()
- Class<?> getObjectType()
- boolean isSingleton()
我们先解释一下这个三个方法的含义:getObjectType指明该FactoryBean产生的Java Bean的类型,getObject则返回Java Bean的具体对象,isSingleton用来指明这个Java Bean是否是单例。
代码其实很简单,我们其实很容易就能看出来FactoryBean的基本用法。但是这里有一点值得注意:我们在xml中定义bean的时候,指定的class是FooFactoryBean,但是代码中实际调用的时候,则是通过Foo.class来获取。也就是说,通过FactoryBean来提供Bean对象,和直接定义一个某类型的Bean对象,达到的效果是相同的;它们之间的区别在于,通过使用FactoryBean,你可以定制更加复杂的对象创建逻辑去满足你的业务需求。从这个角度来看,其实FactoryBean也是以工厂模式的方式在提供对象的获取,不过它只能为某一个特定类型的Java类提供对象的创建。
详细源码可查看:github