BeanFactory和FactoryBean的區(qū)別

1. BeanFactory

BeanFactory定義了 IOC 容器的最基本形式,并提供了 IOC 容器應(yīng)遵守的的最基本的接口,也就是 Spring IOC 所遵守的最底層和最基本的編程規(guī)范。在 Spring 代碼中,BeanFactory 只是個(gè)接口,并不是 IOC 容器的具體實(shí)現(xiàn),但是 Spring 容器給出了很多種實(shí)現(xiàn),如 DefaultListableBeanFactory 、XmlBeanFactory 、 ApplicationContext、ClassPathXmlApplicationContext 等,都是附加了某種功能的實(shí)現(xiàn)。

package org.springframework.beans.factory;  
import org.springframework.beans.BeansException;  
public interface BeanFactory {  
    String FACTORY_BEAN_PREFIX = "&";  
    Object getBean(String name) throws BeansException;  
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;  
    <T> T getBean(Class<T> requiredType) throws BeansException;  
    Object getBean(String name, 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. FactoryBean

FactoryBean是一個(gè)接口,當(dāng)在IOC容器中的Bean實(shí)現(xiàn)了FactoryBean后,通過(guò)getBean(String BeanName)獲取到的Bean對(duì)象并不是FactoryBean的實(shí)現(xiàn)類對(duì)象,而是這個(gè)實(shí)現(xiàn)類中的getObject()方法返回的對(duì)象。要想獲取FactoryBean的實(shí)現(xiàn)類,就要getBean(&BeanName),在BeanName之前加上&。

package org.springframework.beans.factory;  
public interface FactoryBean<T> {  
    T getObject() throws Exception;  
    Class<?> getObjectType();  
    boolean isSingleton();  
} 

下面是一個(gè)應(yīng)用FactoryBean的例子

<beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                     http://www.springframework.org/schema/context
                     http://www.springframework.org/schema/context/spring-context-3.0.xsd
                     http://www.springframework.org/schema/aop
                     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                     http://www.springframework.org/schema/tx
                     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    
 <bean id="student" class="com.spring.bean.Student">  
  <property name="name" value="zhangsan" />  
 </bean>  
 
 <bean id="school" class="com.spring.bean.School">  
 </bean> 
 
 <bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">  
    <property name="type" value="student" />
 </bean> 
</beans>

FactoryBean的實(shí)現(xiàn)類

import org.springframework.beans.factory.FactoryBean;
 
public class FactoryBeanPojo implements FactoryBean{
    private String type;
 
    @Override
    public Object getObject() throws Exception {
        if("student".equals(type)){
            return new Student();           
        }else{
            return new School();
        }
        
    }
 
    @Override
    public Class getObjectType() {
        return School.class;
    }
 
    @Override
    public boolean isSingleton() {
        return true;
    }
 
    public String getType() {
        return type;
    }
 
    public void setType(String type) {
        this.type = type;
    }
}

普通的bean

public class School {
    private String schoolName;
    private String address;
    private int studentNumber;
    public String getSchoolName() {
        return schoolName;
    }
    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public int getStudentNumber() {
        return studentNumber;
    }
    public void setStudentNumber(int studentNumber) {
        this.studentNumber = studentNumber;
    }
    @Override
    public String toString() {
        return "School [schoolName=" + schoolName + ", address=" + address
                + ", studentNumber=" + studentNumber + "]";
    }

測(cè)試類

import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.spring.bean.FactoryBeanPojo;
 
public class FactoryBeanTest {
    public static void main(String[] args){
        String url = "com/spring/config/BeanConfig.xml";
        ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);
        Object school=  cpxa.getBean("factoryBeanPojo");
        FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo");
        System.out.println(school.getClass().getName());
        System.out.println(factoryBeanPojo.getClass().getName());
    }
}

輸出的結(jié)果:

十一月 16, 2016 10:28:24 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1e8ee5c0: startup date [Wed Nov 16 10:28:24 CST 2016]; root of context hierarchy
十一月 16, 2016 10:28:24 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/spring/config/BeanConfig.xml]
十一月 16, 2016 10:28:24 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@35b793ee: defining beans [student,school,factoryBeanPojo]; root of factory hierarchy
com.spring.bean.Student
com.spring.bean.FactoryBeanPojo

從結(jié)果上可以看到當(dāng)從IOC容器中獲取FactoryBeanPojo對(duì)象的時(shí)候,用getBean(String BeanName)獲取的確是Student對(duì)象,可以看到在FactoryBeanPojo中的type屬性設(shè)置為student的時(shí)候,會(huì)在getObject()方法中返回Student對(duì)象。所以說(shuō)從IOC容器獲取實(shí)現(xiàn)了FactoryBean的實(shí)現(xiàn)類時(shí),返回的卻是實(shí)現(xiàn)類中的getObject方法返回的對(duì)象,要想獲取FactoryBean的實(shí)現(xiàn)類,得在getBean(String BeanName)中的BeanName之前加上&,寫(xiě)成getBean(String &BeanName)。

3.BeanFactory和FactoryBean的區(qū)別

BeanFactory和FactoryBean其實(shí)沒(méi)有什么比較性的,只是兩者的名稱特別接近,所以有時(shí)候會(huì)拿出來(lái)比較一番,BeanFactory是提供了IOC容器最基本的形式,給具體的IOC容器的實(shí)現(xiàn)提供了規(guī)范,F(xiàn)actoryBean可以說(shuō)為IOC容器中Bean的實(shí)現(xiàn)提供了更加靈活的方式,F(xiàn)actoryBean在IOC容器的基礎(chǔ)上給Bean的實(shí)現(xiàn)加上了一個(gè)簡(jiǎn)單工廠模式和裝飾模式,我們可以在getObject()方法中靈活配置。其實(shí)在Spring源碼中有很多FactoryBean的實(shí)現(xiàn)類,要想深入準(zhǔn)確的理解FactoryBean,只有去讀讀Spring源碼了。

原文:https://blog.csdn.net/wangbiao007/article/details/53183764

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容