文章目錄
- 前言
- 一、為什麼會有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一一對應起來。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLxcGVPFzZq10dNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4UTM1MTO1AjM0ADNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
這種方式的弊端是所有的
bean
都需要事先定義好,但是有時候,有的一些
bean
,我們隻知道它大概的樣子,但是無法事先定義出其具體的功能。就好比,我們知道它是一隻鳥,但是不知道是什麼種類的鳥,隻有在代碼執行的時候,我才知道是什麼種類的鳥。 如此表達可能不太直覺,這裡可以直接聯想出
mybatis
中的
mapper
。例如
UserMapper
。
在定義
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
。
大家可以自行打開源碼檢視,通過上圖的流程即可發現。每一個
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呢?