使用过Spring的同学一定对BeanFactory不会陌生,因为Spring其中一个最大的特性就是Bean容器,顾名思义就是用来存放并提供Java Bean的。但是,估计不少人对FactoryBean鲜有耳闻。这两个词看着非常类似,但是概念和功能却截然不同。

    我们先重新来看看BeanFactory,从名字我们就可以看出来它其实是一个Bean工厂,通过工厂模式来为我们提供Java Bean的使用。通过BeanFactory的使用,调用者不需要知道Bean的具体创建细节,直接通过BeanID或Bean类型来获取即可,非常便利。所以,我们抓住了本质:BeanFactory是一个工厂类。

    那FactoryBean呢?如果还是从名字上分析,那它就是一个Bean?那它和普通的Java Bean又有什么区别呢?首先,我们先确认,它确实就是一个Bean!接下来,我们就来好好分析一下这个所谓的FacoryBean到底有什么神奇之处。我们先来看一段示例代码。

    1. public class FactoryBeanDemo {
    2. public static void main(String[] args) {
    3. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/factory-bean-demo.xml");
    4. Foo foo = applicationContext.getBean(Foo.class);
    5. foo.hello();
    6. }
    7. }
    8. public class FooFactoryBean implements FactoryBean<Foo> {
    9. @Override
    10. public Foo getObject() throws Exception {
    11. // 这里可以定义更加复杂的对象创建逻辑
    12. return new Foo("I am a Foo instance from FooFactoryBean");
    13. }
    14. @Override
    15. public Class<?> getObjectType() {
    16. return Foo.class;
    17. }
    18. @Override
    19. public boolean isSingleton() {
    20. return true;
    21. }
    22. }
    23. public class Foo {
    24. private String msg;
    25. public Foo(String msg) {
    26. this.msg = msg;
    27. }
    28. public void hello(){
    29. System.out.println(msg);
    30. }
    31. }
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans
    3. xmlns="http://www.springframework.org/schema/beans"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
    7. >
    8. <bean class="com.lmmmowi.java.explore.spring.beans.factory_bean_demo.FooFactoryBean" />
    9. </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