天天看點

【spring】BeanFactory與FactoryBean的差別前言一、為什麼會有FactoryBean?二、通過源碼深入學習FactoryBean

文章目錄

  • 前言
  • 一、為什麼會有FactoryBean?
  • 二、通過源碼深入學習FactoryBean

前言

      常說spring的核心是ioc,ioc的核心是BeanFactory。然而在spring中還有一個很容易讓人混淆的詞FactoryBean。本文通過一些mybatis源碼來講述其差別,請大家參考。

一、為什麼會有FactoryBean?

BeanFactory

是在學習IOC第一課的時候就遇到的。它是生産bean的工廠。在此工廠中,我們可以生産出我們想要的bean,并且通過

getBean

接口進行擷取。

      但是在通過

getBean

擷取bean之前,我們需要事先定義這個bean漲什麼樣子,或者說它由哪些元件組成。定義的方式有很多,可以通過xml進行定義,或者在代碼中通過注解(@Bean、@Service)進行定義。就好比一個Controller,在最原始的xml配置bean的時候,我們需要定義它是由哪些service組成,然後一點點的配置好。xml要與Controller的service一一對應起來。

【spring】BeanFactory與FactoryBean的差別前言一、為什麼會有FactoryBean?二、通過源碼深入學習FactoryBean

      這種方式的弊端是所有的

bean

都需要事先定義好,但是有時候,有的一些

bean

,我們隻知道它大概的樣子,但是無法事先定義出其具體的功能。就好比,我們知道它是一隻鳥,但是不知道是什麼種類的鳥,隻有在代碼執行的時候,我才知道是什麼種類的鳥。 如此表達可能不太直覺,這裡可以直接聯想出

mybatis

中的

mapper

。例如

UserMapper

【spring】BeanFactory與FactoryBean的差別前言一、為什麼會有FactoryBean?二、通過源碼深入學習FactoryBean

      在定義

UserMapper

的時候,我們知道其最後執行的xml的sql語句。而且這樣的

mapper

又很多,可能還會有更多的

OrderMapper、GoodsMapper

等等。 如果每一個都一一定義的話,會非常的麻煩。但是,我們發現

mapper

中的功能都是與資料庫互動的代碼。是以規範其寫法,通過定義一些标準的寫法,就可以簡化其定義過程。這樣便出現了

@Select

注解和

@Update

注解(還有xml的标簽),這樣我們隻需要在注解中寫入對應的sql,在代碼執行時候,執行對應的sql。

      這樣一想可以認為是所有的mapper就是鳥,但是不知道它是什麼鳥,或者這個鳥是做什麼的(不知道每個

mapper

的功能),在真正建立它的時候,才去關注它具體的内容。

      這樣

FactoryBean

的就有了其意義,它可以定義出一種類型的Bean,并且在建立的時候再去實作其具體的功能。裡面有三個方法。

  • getObject 擷取

    bean

    方法,在此方法中,我們可以自己定義一個對象,然後自行修改其建立過程。通過這個方法,我們可以在

    mapper

    建立的時候再實作其具體的功能。
  • getObjectType 擷取這類的類型。
  • isSingleton 是否單例。
public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}
           

二、通過源碼深入學習FactoryBean

      如果還沒有了解

FactoryBean

。我們可以通過學習

mybatis

源碼,來更加深入的了解FactoryBean。

      這裡帶領大家了解下

Mybatis

MapperFactoryBean

,這個是生成

Mapper

FactoryBean

【spring】BeanFactory與FactoryBean的差別前言一、為什麼會有FactoryBean?二、通過源碼深入學習FactoryBean

      大家可以自行打開源碼檢視,通過上圖的流程即可發現。每一個

mapper

是通過

MapperFactoryBean

getObject

方法進行建立,最後生成一個代理類。在代理類中對Mapper對應的注解資訊進行解析。

      相信跟一下

mybatis

的源碼之後,對

FactoryBean

會有更加深入的了解。雖然在開發時用

FactoryBean

的機會并不多,但是源碼中會經常遇到,例如

spring cloud

feign

元件,裡面肯定也會看到

FactoryBean

的身影。

對于mybatis和feign,可以很輕松的發現其共同點:

  • 存在一種類型的bean。

    mybatis

    Mapper

    ,

    feign

    FeignClient

  • 這種

    bean

    功能單一。

    mapper

    隻跟資料庫做互動。

    FeignClient

    隻是接口調用。

      還有我們常用的定時器架構quartz架構。裡面也有JobDetailFactoryBean。Redis中有RedisClientFactoryBean。security架構的UserDetailsManagerResourceFactoryBean。其實他們都是有一個共同的特點,就是生産的bean是一種類型,在建立的過程中在實作其功能。到這是不是已經了解了FactoryBean呢?

繼續閱讀