欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡單了解Spring中BeanFactory與FactoryBean的區(qū)別

 更新時(shí)間:2019年12月24日 10:13:09   作者:何其有靜  
這篇文章主要介紹了簡單了解Spring中BeanFactory與FactoryBean的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了簡單了解Spring中BeanFactory與FactoryBean的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

在Spring中有BeanFactory和FactoryBean這2個(gè)接口,從名字來看很相似,比較容易搞混。

一、BeanFactory

BeanFactory是一個(gè)接口,它是Spring中工廠的頂層規(guī)范,是SpringIoc容器的核心接口,它定義了getBean()、containsBean()等管理Bean的通用方法。Spring的容器都是它的具體實(shí)現(xiàn)如:

  • DefaultListableBeanFactory
  • XmlBeanFactory
  • ApplicationContext

這些實(shí)現(xiàn)類又從不同的維度分別有不同的擴(kuò)展。

1.1 BenaFactory源碼

public interface BeanFactory {

  /**
   * 用來獲得實(shí)例的引用,并且區(qū)分FactoryBean區(qū)分。
   * 如果使用bean的名字myJndiObject獲取FactoryBean,返回的是一個(gè)工廠,而不是工廠的實(shí)例;如果需要獲得工廠實(shí)例,需要轉(zhuǎn)義。
   */
  String FACTORY_BEAN_PREFIX = "&";

  /**
   * 根據(jù)bean的名稱,獲取指定的bean實(shí)例,該實(shí)例可以是共享的,也可以是獨(dú)立的.
   */
  Object getBean(String name) throws BeansException;

  /**
   * 根據(jù)bean的名稱,獲取指定的bean實(shí)例,該實(shí)例可以是共享的,也可以是獨(dú)立的.并且增加了一個(gè)類型的檢驗(yàn)。
   */
  <T> T getBean(String name, Class<T> requiredType) throws BeansException;

  Object getBean(String name, Object... args) throws BeansException;

  /**
   * 根據(jù)給定類型返回匹配的bean實(shí)例.
   */
  <T> T getBean(Class<T> requiredType) throws BeansException;

  <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

  /**
   * 檢查spring的bean容器中是否包含有該bean
   */
  boolean containsBean(String name);

  /**
   * 判斷bean的作用域是否是singleton
   */
  boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

  /**
   * 判斷bena的作用域是否是prototype
   */
  boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

  /**
   * 檢查給定名稱的bean是否和指定類型匹配.更確卻的說是通過檢查給定的bean,返回指定類型的目標(biāo)對象
   */
  boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

  boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

  /**
   * 獲取給定名稱的bean的class類型
   */
  Class<?> getType(String name) throws NoSuchBeanDefinitionException;

  /**
   * 獲取給定bean名稱的別名,如果根據(jù)別名檢索,將會獲得原始bean名稱。
   * 
  String[] getAliases(String name);

}

1.2 使用場景

  • 從Ioc容器中獲取Bean(byName or byType):context.getBean("father", Father.class)、context.getBean("father")
  • 檢索Ioc容器中是否包含指定的Bean: context.containsBean("father")
  • 判斷Bean是否為單例: context.isSingleton("father")

二、FactoryBean

首先它是一個(gè)Bean,但又不僅僅是一個(gè)Bean。它是一個(gè)能生產(chǎn)或修飾對象生成的工廠Bean,類似于設(shè)計(jì)模式中的工廠模式和裝飾器模式。它能在需要的時(shí)候生產(chǎn)一個(gè)對象,且不僅僅限于它自身,它能返回任何Bean的實(shí)例。

2.1 FactoryBean源碼

public interface FactoryBean<T> {

  /**
   * 從工廠中獲取bean實(shí)例
   */
  T getObject() throws Exception;

  /**
   * 從工廠中獲取bean實(shí)例對象的類型
   */
  Class<?> getObjectType();

  /**
   * 工廠創(chuàng)建的對象是否是單例
   */
  boolean isSingleton();

}

從它定義的接口可以看出,F(xiàn)actoryBean表現(xiàn)的是一個(gè)工廠的職責(zé)。 即一個(gè)Bean A如果實(shí)現(xiàn)了FactoryBean接口,那么A就變成了一個(gè)工廠,根據(jù)A的名稱獲取到的實(shí)際上是工廠調(diào)用getObject()返回的對象,而不是A本身,如果要獲取工廠A自身的實(shí)例,那么需要在名稱前面加上'&'符號。

  • getObject('name')返回工廠中的實(shí)例
  • getObject('&name')返回工廠本身的實(shí)例

通常情況下,bean 無須自己實(shí)現(xiàn)工廠模式,Spring 容器擔(dān)任了工廠的 角色;但少數(shù)情況下,容器中的 bean 本身就是工廠,作用是產(chǎn)生其他 bean 實(shí)例。由工廠 bean 產(chǎn)生的其他 bean 實(shí)例,不再由 Spring 容器產(chǎn)生,因此與普通 bean 的配置不同,不再需要提供 class 元素。

2.2 示例

先定義一個(gè)Bean實(shí)現(xiàn)FactoryBean接口:

@Component
public class MyBean implements FactoryBean {
  private String message;
  public MyBean() {
    this.message = "通過構(gòu)造方法初始化實(shí)例";
  }

  public MyBean(String message) {
    this.message = message;
  }

  @Override
  public Object getObject() throws Exception {
    // 這里并不一定要返回MyBean自身的實(shí)例,可以是其他任何對象的實(shí)例
    return new MyBean("通過FactoryBean.getObject()創(chuàng)建實(shí)例");
  }
  @Override
  public Class<?> getObjectType() {
    return MyBean.class;
  }
  public String getMessage() {
    return message;
  }

  @Override
  public boolean isSingleton() {
    return false;
  }
}

MyBean實(shí)現(xiàn)了FactoryBean接口的三個(gè)方法,getObject()是可以返回任何對象的實(shí)例的,這里測試就返回MyBean自身實(shí)例,且返回前給message字段賦值。同時(shí)在構(gòu)造方法中也為message賦值。然后測試代碼中先通過名稱獲取Bean實(shí)例,打印message的內(nèi)容,再通過&+名稱獲取實(shí)例并打印message內(nèi)容。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = HelloApplication.class)
public class FactoryBeanTest {
  @Autowired
  private ApplicationContext context;
  @Test
  public void test() {
    MyBean myBean1 = (MyBean) context.getBean("myBean");//返回工廠中的實(shí)例,調(diào)用FactoryBean.getObject()創(chuàng)建實(shí)例
    System.out.println("myBean1 = " + myBean1.getMessage());
    MyBean myBean2 = (MyBean) context.getBean("&myBean");//返回工廠本身,通過構(gòu)造方法初始化實(shí)例
    System.out.println("myBean2 = " + myBean2.getMessage());
    System.out.println("myBean1.equals(myBean2) = " + myBean1.equals(myBean2));
  }
}

打印結(jié)果:

myBean1 = 通過FactoryBean.getObject()創(chuàng)建實(shí)例
myBean2 = 通過構(gòu)造方法初始化實(shí)例
myBean1.equals(myBean2) = false

2.3 使用場景

說了這么多,為什么要有FactoryBean這個(gè)東西呢,有什么具體的作用嗎?

FactoryBean在Spring中最為典型的一個(gè)應(yīng)用就是用來創(chuàng)建AOP的代理對象。

我們知道AOP實(shí)際上是Spring在運(yùn)行時(shí)創(chuàng)建了一個(gè)代理對象,也就是說這個(gè)對象,是我們在運(yùn)行時(shí)創(chuàng)建的,而不是一開始就定義好的,這很符合工廠方法模式。更形象地說,AOP代理對象通過Java的反射機(jī)制,在運(yùn)行時(shí)創(chuàng)建了一個(gè)代理對象,在代理對象的目標(biāo)方法中根據(jù)業(yè)務(wù)要求織入了相應(yīng)的方法。這個(gè)對象在Spring中就是——ProxyFactoryBean。

所以,F(xiàn)actoryBean為我們實(shí)例化Bean提供了一個(gè)更為靈活的方式,我們可以通過FactoryBean創(chuàng)建出更為復(fù)雜的Bean實(shí)例。

三、區(qū)別

  • 他們兩個(gè)都是個(gè)工廠,但FactoryBean本質(zhì)上還是一個(gè)Bean,也歸BeanFactory管理
  • BeanFactory是Spring容器的頂層接口,F(xiàn)actoryBean更類似于用戶自定義的工廠接口。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 單向隊(duì)列及環(huán)形隊(duì)列的實(shí)現(xiàn)原理

    Java 單向隊(duì)列及環(huán)形隊(duì)列的實(shí)現(xiàn)原理

    本文主要介紹了Java 單向隊(duì)列及環(huán)形隊(duì)列的實(shí)現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Java細(xì)數(shù)IO流底層原理到方法使用

    Java細(xì)數(shù)IO流底層原理到方法使用

    IO主要用于設(shè)備之間的數(shù)據(jù)傳輸,Java將操作數(shù)據(jù)流的功能封裝到了IO包中,這篇文章主要給大家介紹了關(guān)于Java新手學(xué)習(xí)之IO流簡單使用的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • java實(shí)現(xiàn)郵件發(fā)送

    java實(shí)現(xiàn)郵件發(fā)送

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • java編程實(shí)現(xiàn)優(yōu)先隊(duì)列的二叉堆代碼分享

    java編程實(shí)現(xiàn)優(yōu)先隊(duì)列的二叉堆代碼分享

    這篇文章主要介紹了java編程實(shí)現(xiàn)優(yōu)先隊(duì)列的二叉堆代碼分享,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 淺談一下Spring的核心基礎(chǔ)IOC與DI

    淺談一下Spring的核心基礎(chǔ)IOC與DI

    這篇文章主要介紹了Spring的核心基礎(chǔ)IOC與DI的詳細(xì)用法,spring技術(shù)是現(xiàn)在企業(yè)開發(fā)中幾乎必備的技術(shù)選型,那么學(xué)好spring就很重要,本篇著重講解spring的核心機(jī)制,IOD與DI,一起來看看吧
    2023-03-03
  • java中url漢字編碼互相轉(zhuǎn)換實(shí)例

    java中url漢字編碼互相轉(zhuǎn)換實(shí)例

    這篇文章介紹了java中url漢字編碼互相轉(zhuǎn)換實(shí)例,有需要的朋友可以參考一下
    2013-10-10
  • Spring(一):IOC如何推導(dǎo)和理解

    Spring(一):IOC如何推導(dǎo)和理解

    下面小編就為大家?guī)硪黄斦凷pring對IOC的理解(推薦篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2021-07-07
  • MySQL如何設(shè)置自動增長序列SEQUENCE的方法

    MySQL如何設(shè)置自動增長序列SEQUENCE的方法

    本文主要介紹了MySQL如何設(shè)置自動增長序列SEQUENCE的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • java啟動參數(shù)之謎的排查過程

    java啟動參數(shù)之謎的排查過程

    在日常操作中,相信很多人對Java啟動參數(shù)存在疑惑,下面這篇文章主要給大家介紹了關(guān)于java啟動參數(shù)之謎的排查過程,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 基于javax.validation結(jié)合spring的最佳實(shí)踐

    基于javax.validation結(jié)合spring的最佳實(shí)踐

    這篇文章主要介紹了javax.validation結(jié)合spring的最佳實(shí)踐,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07

最新評論