Spring中FactoryBean與BeanFactory的區別


版本:spring-framework-4.1

一概述

BeanFactory 與 FactoryBean的區別, 兩個名字很像,面試中也經常遇到,所以容易搞混,現從源碼以及示例兩方面來分析。

二、源碼

2.1 BeanFactory

BeanFactory定義了 IOC 容器的最基本形式,並提供了 IOC 容器應遵守的的最基本的接口,也就是 Spring IOC 所遵守的最底層和最基本的編程規范。

BeanFactory僅是個接口,並不是IOC容器的具體實現,具體的實現有:如 DefaultListableBeanFactory 、 XmlBeanFactory 、 ApplicationContext 等。

public interface BeanFactory {
    //FactoryBean前綴
    String FACTORY_BEAN_PREFIX = "&";

    //根據名稱獲取Bean對象
    Object getBean(String name) throws BeansException;

    ///根據名稱、類型獲取Bean對象
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    //根據類型獲取Bean對象
    <T> T getBean(Class<T> requiredType) throws BeansException;

    //根據名稱獲取Bean對象,帶參數
    Object getBean(String name, Object... args) throws BeansException;

    //根據類型獲取Bean對象,帶參數
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    //是否存在
    boolean containsBean(String name);

    //是否為單例
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    //是否為原型(多實例)
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    //名稱、類型是否匹配
    boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;

    //獲取類型
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    //根據實例的名字獲取實例的別名
    String[] getAliases(String name);
}

2.1 FactoryBean

FactoryBean工廠類接口,用戶可以通過實現該接口定制實例化 Bean 的邏輯。

public interface FactoryBean<T> {

    //FactoryBean 創建的 Bean 實例
    T getObject() throws Exception;

    //返回 FactoryBean 創建的 Bean 類型
    Class<?> getObjectType();

    //返回由 FactoryBean 創建的 Bean 實例的作用域是 singleton 還是 prototype
    boolean isSingleton();
}

三、示例

3.1 普通bean

public class Dog {
    private String msg;

    public Dog(String msg){
        this.msg=msg;
    }
    public void run(){
        System.out.println(msg);
    }
}

3.2 實現了FactoryBean的bean

public class DogFactoryBean implements FactoryBean<Dog>{

    public Dog getObject() throws Exception {
        return new Dog("DogFactoryBean.run");
    }

    public Class<?> getObjectType() {
        return DogFactoryBean.class;
    }

    public boolean isSingleton() {
        return false;
    }
}

3.3 配置文件

<bean id="dog" class="com.bean.Dog" >
    <constructor-arg value="Dog.run"/>
</bean>

<bean id="dogFactoryBean" class="com.bean.DogFactoryBean" />

3.4 測試

@Test
public void testBean() throws Exception {
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

    Dog dog1 = (Dog) ctx.getBean("dog");
    dog1.run();

    Dog dog2 = (Dog) ctx.getBean("dogFactoryBean");
    dog2.run();

    //使用&前綴可以獲取FactoryBean本身
    FactoryBean dogFactoryBean = (FactoryBean) ctx.getBean("&dogFactoryBean");
    Dog dog3= (Dog) dogFactoryBean.getObject();
    dog3.run();
}

結果輸出:

Dog.run
DogFactoryBean.run
DogFactoryBean.run

四、總結

通過以上源碼和示例來看,基本上能印證以下結論,也就是二者的區別。

  1. BeanFactory是個Factory,也就是 IOC 容器或對象工廠,所有的 Bean 都是由 BeanFactory( 也就是 IOC 容器 ) 來進行管理。

  2. FactoryBean是一個能生產或者修飾生成對象的工廠Bean,可以在IOC容器中被管理,所以它並不是一個簡單的Bean。當使用容器中factory bean的時候,該容器不會返回factory bean本身,而是返回其生成的對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM