Spring中BeanFactory和FactoryBean的區(qū)別

1、 BeanFactory

  BeanFactory,以Factory結(jié)尾,表示它是一個(gè)工廠類(接口),它是負(fù)責(zé)生產(chǎn)和管理bean的一個(gè)工廠。BeanFactory只是個(gè)接口,并不是IOC容器的具體實(shí)現(xiàn),它為IOC容器提供了基本的規(guī)范。在Spring中給出了BeanFactory的很多種實(shí)現(xiàn),如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一個(gè),XmlBeanFactory類將持有XML配置元數(shù)據(jù),并用它來(lái)構(gòu)建一個(gè)完全可配置的系統(tǒng)或應(yīng)用。

BeanFactory和ApplicationContext是Spring框架的兩個(gè)IOC容器,現(xiàn)在一般使用ApplicationnContext,其不但包含了BeanFactory的作用,同時(shí)還進(jìn)行更多的擴(kuò)展。? BeanFacotry是Spring中比較原始的Factory。原始的BeanFactory無(wú)法支持Spring的許多插件,如AOP功能、Web應(yīng)用等。ApplicationContext接口,它由BeanFactory接口派生而來(lái),ApplicationContext包含BeanFactory的所有功能,通常建議使用ApplicationContext。ApplicationContext以一種更加面向框架的方式工作以及對(duì)上下文進(jìn)行分層和實(shí)現(xiàn)繼承。另外需要說(shuō)明一點(diǎn)的是在不使用Spring框架之前,我們的service層中要使用dao層的對(duì)象,不得不在service層中new一個(gè)對(duì)象,這樣存在層與層之間的依賴。有了Spring框架提供的IOC容器service層要用dao層對(duì)象需要配置到xml配置文件中,至于對(duì)象是怎么創(chuàng)建的,關(guān)系是怎么組合的都交給了Spring框架去實(shí)現(xiàn)。

Resource resource = new FileSystemResource("beans.xml");

BeanFactory factory = new XmlBeanFactory(resource);

ClassPathResource resource = new ClassPathResource("beans.xml");

BeanFactory factory = new XmlBeanFactory(resource);

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"});

BeanFactory factory = (BeanFactory) context;

BeanFactory的用法基本就是這些了,接著使用getBean(String beanName)方法就可以取得bean的實(shí)例;BeanFactory提供的方法及其簡(jiǎn)單,僅提供了六種方法供客戶調(diào)用,如下所示。

  boolean containsBean(String beanName) 判斷工廠中是否包含給定名稱的bean定義,若有則返回true;

  Object getBean(String) 返回給定名稱注冊(cè)的bean實(shí)例。根據(jù)bean的配置情況,如果是singleton模式將返回一個(gè)共享實(shí)例,否則將返回一個(gè)新建的實(shí)例,如果沒有找到指定bean,該方法可能會(huì)拋出異常;

  Object getBean(String name, Class clazz) 返回以給定名稱注冊(cè)的bean實(shí)例,并轉(zhuǎn)換為給定class類型;

  Class getType(String name) 返回給定名稱的bean的Class,如果沒有找到指定的bean實(shí)例,則排除NoSuchBeanDefinitionException異常;

  boolean isSingleton(String name) 判斷給定名稱的bean定義是否為單例模式;

  String[] getAliases(String name) 返回給定bean名稱的所有別名。

2,F(xiàn)actoryBean

????一般情況下,Spring通過(guò)反射機(jī)制利用配置文件中的<bean>標(biāo)簽的class屬性指定實(shí)現(xiàn)類實(shí)例化Bean,在某些情況下,實(shí)例化Bean過(guò)程比較復(fù)雜,如果按照傳統(tǒng)的方式,則需要在<bean>中提供大量的配置信息。配置方式的靈活性受到限制,這時(shí)采用編碼的方式可能會(huì)得到一個(gè)簡(jiǎn)單的方案。Spring為此提供了一個(gè)org.springframework.bean.factory.FactoryBean的工廠類接口,用戶可以通過(guò)實(shí)現(xiàn)該接口定制實(shí)例化Bean的邏輯。FactoryBean接口對(duì)于Spring框架來(lái)說(shuō)占據(jù)重要的地位,Spring自身就提供了70多個(gè)FactoryBean的實(shí)現(xiàn)。它們隱藏了實(shí)例化一些復(fù)雜Bean的細(xì)節(jié),給上層應(yīng)用帶來(lái)了便利。從Spring3.0開始,F(xiàn)actoryBean開始支持泛型,即接口聲明改為FactoryBean<T>的形式。以Bean結(jié)尾,表示它是一個(gè)Bean,不同于普通Bean的是:它是實(shí)現(xiàn)了FactoryBean<T>接口的Bean,根據(jù)該Bean的ID從BeanFactory中獲取的實(shí)際上是FactoryBean的getObject()返回的對(duì)象,而不是FactoryBean本身,如果要獲取FactoryBean對(duì)象,請(qǐng)?jiān)趇d前面加一個(gè)&符號(hào)來(lái)獲取。

下面演示FactoryBean的使用。

首先咱們一起來(lái)看下FactoryBean的源代碼如下:

public interface FactoryBean<T> {

? ? /*

? ? * 獲取bean對(duì)應(yīng)的實(shí)例對(duì)象

? ? */

? ? T getObject() throws Exception;

? ? /**

? ? * 獲取factoryBean獲取到的實(shí)例類型

? ? */

? ? Class<?> getObjectType();

? ? /**

? ? * factoryBean創(chuàng)建的實(shí)例是否是單實(shí)例

? ? */

? ? boolean isSingleton();

}

可以發(fā)現(xiàn)FactoryBean是一個(gè)接口主要有3個(gè)方法,每個(gè)方法的意思代碼中都有注釋這個(gè)就不重復(fù)了。

下面我們通過(guò)FactoryBean來(lái)創(chuàng)建一個(gè)簡(jiǎn)單的Student的bean,代碼如下:

/**

* 創(chuàng)建一個(gè)自定義的Spring的FactoryBean

*/

public class CustomFactoryBean implements FactoryBean<Student>{

? ? public Student getObject() throws Exception {

? ? ? ? return new Student();

? ? }

? ? public Class<?> getObjectType() {

? ? ? ? return Student.class;

? ? }

? ? /**

? ? * 是否是單實(shí)例的,可以通過(guò)改變返回值測(cè)試效果

? ? */

? ? public boolean isSingleton() {

? ? ? ? return true;

? ? }

}

再在MainConfig主配置中加入一個(gè)bean如下:

/**

* 定義一個(gè)注解配置文件必須要加上@Configuration注解

*/

@Configuration

public class MainConfig {

? ? /**

? ? * 定義一個(gè)bean對(duì)象

? ? */

? ? @Bean

? public CustomFactoryBean getMyFactoryBean(){

? ? return new CustomFactoryBean();

}

}

測(cè)試代碼如下:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);

Object object = applicationContext2.getBean("getMyFactoryBean");

System.out.println("實(shí)例bean為:"+object);

Object object2 = applicationContext2.getBean("&getMyFactoryBean");

System.out.println("實(shí)例bean為:"+object2);

運(yùn)行結(jié)果如下:

實(shí)例bean為 :com.test.bean.Student@3bd94634

實(shí)例bean為 : com.test.bean.CustomFactoryBean@58a90037

????從上面的測(cè)試結(jié)果我們知道,根據(jù)該Bean的ID從BeanFactory中獲取的實(shí)際上是FactoryBean的getObject()返回的對(duì)象,而不是FactoryBean本身,如果要獲取FactoryBean對(duì)象,請(qǐng)?jiān)趇d前面加一個(gè)&符號(hào)來(lái)獲取。

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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