中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解Spring中BeanFactory與FactoryBean的區別

發布時間:2021-10-15 17:46:15 來源:億速云 閱讀:115 作者:柒染 欄目:編程語言

這篇文章將為大家詳細講解有關如何理解Spring中BeanFactory與FactoryBean的區別,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

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

一、BeanFactory

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

DefaultListableBeanFactory  XmlBeanFactory  ApplicationContext

這些實現類又從不同的維度分別有不同的擴展。

1.1 BenaFactory源碼

public interface BeanFactory {  /**   * 用來獲得實例的引用,并且區分FactoryBean區分。   * 如果使用bean的名字myJndiObject獲取FactoryBean,返回的是一個工廠,而不是工廠的實例;如果需要獲得工廠實例,需要轉義。   */  String FACTORY_BEAN_PREFIX = "&";  /**   * 根據bean的名稱,獲取指定的bean實例,該實例可以是共享的,也可以是獨立的.   */  Object getBean(String name) throws BeansException;  /**   * 根據bean的名稱,獲取指定的bean實例,該實例可以是共享的,也可以是獨立的.并且增加了一個類型的檢驗。   */  <T> T getBean(String name, Class<T> requiredType) throws BeansException;  Object getBean(String name, Object... args) throws BeansException;  /**   * 根據給定類型返回匹配的bean實例.   */  <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,返回指定類型的目標對象   */  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名稱的別名,如果根據別名檢索,將會獲得原始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

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

2.1 FactoryBean源碼

public interface FactoryBean<T> {  /**   * 從工廠中獲取bean實例   */  T getObject() throws Exception;  /**   * 從工廠中獲取bean實例對象的類型   */  Class<?> getObjectType();  /**   * 工廠創建的對象是否是單例   */  boolean isSingleton();}

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

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

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

2.2 示例

先定義一個Bean實現FactoryBean接口:

@Componentpublic class MyBean implements FactoryBean {  private String message;  public MyBean() {    this.message = "通過構造方法初始化實例";  }  public MyBean(String message) {    this.message = message;  }  @Override  public Object getObject() throws Exception {    // 這里并不一定要返回MyBean自身的實例,可以是其他任何對象的實例    return new MyBean("通過FactoryBean.getObject()創建實例");  }  @Override  public Class<?> getObjectType() {    return MyBean.class;  }  public String getMessage() {    return message;  }  @Override  public boolean isSingleton() {    return false;  }}

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

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

打印結果:

myBean1 = 通過FactoryBean.getObject()創建實例myBean2 = 通過構造方法初始化實例myBean1.equals(myBean2) = false

2.3 使用場景

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

FactoryBean在Spring中最為典型的一個應用就是用來創建AOP的代理對象。

我們知道AOP實際上是Spring在運行時創建了一個代理對象,也就是說這個對象,是我們在運行時創建的,而不是一開始就定義好的,這很符合工廠方法模式。更形象地說,AOP代理對象通過Java的反射機制,在運行時創建了一個代理對象,在代理對象的目標方法中根據業務要求織入了相應的方法。這個對象在Spring中就是——ProxyFactoryBean。

所以,FactoryBean為我們實例化Bean提供了一個更為靈活的方式,我們可以通過FactoryBean創建出更為復雜的Bean實例。

三、區別

他們兩個都是個工廠,但FactoryBean本質上還是一個Bean,也歸BeanFactory管理  BeanFactory是Spring容器的頂層接口,FactoryBean更類似于用戶自定義的工廠接口。

關于如何理解Spring中BeanFactory與FactoryBean的區別就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沂南县| 衡阳县| 化州市| 上林县| 洛扎县| 克东县| 祁东县| 祁连县| 苏尼特左旗| 鹤峰县| 曲松县| 玛沁县| 涞水县| 鸡泽县| 乌海市| 木兰县| 收藏| 中阳县| 徐水县| 阿尔山市| 襄汾县| 海兴县| 萨迦县| 田阳县| 芦溪县| 涞水县| 阿克苏市| 丰都县| 定陶县| 二连浩特市| 抚宁县| 榕江县| 临江市| 安乡县| 边坝县| 沁水县| 祁门县| 佛冈县| 申扎县| 曲水县| 曲麻莱县|