版本: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
四、總結
通過以上源碼和示例來看,基本上能印證以下結論,也就是二者的區別。
-
BeanFactory是個Factory,也就是 IOC 容器或對象工廠,所有的 Bean 都是由 BeanFactory( 也就是 IOC 容器 ) 來進行管理。
-
FactoryBean是一個能生產或者修飾生成對象的工廠Bean,可以在IOC容器中被管理,所以它並不是一個簡單的Bean。當使用容器中factory bean的時候,該容器不會返回factory bean本身,而是返回其生成的對象。