天天看點

使用FactoryBean接口實作自定義bean初始化

使用FactoryBean接口實作自定義bean初始化

       本文所要介紹的FactoryBean是Spring中定義的一個接口,當把它的實作類定義為BeanFactory中的一個bean,我們在擷取其對應的bean時實際上擷取的是FactoryBean所包含的那個對象,而不是它本身。我們先來看一下FactoryBean的定義。

       我們可以看到FactoryBean是使用了泛型的,表示其對應産生的Bean是什麼類型的對象。我們來看一個實作。

       上面代碼中定義了一個UserFactoryBean,用以産生一個單例的User對象。可以看到,我們在getObject()方法中使用了同步塊來保證産生的bean永遠是同一個對象。其實這個并不是必須的。在初始化時BeanFactory調用FactoryBean建立bean時就是同步的,而且BeanFactory建立bean時預設是單例的,也就意味着FactoryBean的getObject方法在BeanFactory中定義為單例的時候隻會調用一次。但有一種情況例外,那就是如果定義bean時指定了“lazy-init=true”時,那就意味着該bean隻有在用到的時候才會進行初始化,這個時候如果剛好兩個線程同時需要使用,就會出現在兩個線程中同時調用FactoryBean的getObject方法進行bean的初始化,如不加控制就會出現兩個執行個體。為保證隻有一個執行個體,getObject方法内部需要是同步的。

       此外,需要注意的是FactoryBean的isSingleton方法傳回結果表示目前FactoryBean産生的bean是否是單例形式,即每次請求getObject()方法傳回的是否都是同一個bean對象。其實FactoryBean更多的是在Spring内部使用,isSingleton隻是用來表示目前傳回的bean對象是否可以用BeanFactory緩存的一個标志。

       上面示例對象的Spring配置檔案如下:

       對于一個FactoryBean接口實作類定義的bean其實Spring将執行個體化兩個bean,一個是FactoryBean本身對應的bean,另一個是FactoryBean産生的對象對應的bean。是以當我們在通過注解方式注入一個FactoryBean執行個體對應的bean時,既可以把它當做一個FactoryBean進行注入,也可以把它當做一個對應産生的執行個體進行注入。而如果是自己直接從ApplicationContext中擷取的話,則直接通過FactoryBean實作類定義的bean名稱擷取到的是FactoryBean實作類産生的對象。如在上面示例中,如果我們通過ApplicationContext的getBean(“userFactoryBean”)擷取到的就将是對應産生的User對象,如果我們需要擷取到對應的FactoryBean本身,則可以在對應的FactoryBean實作類定義的bean名稱前加上“&”進行擷取,如上如果我們要擷取到UserFactoryBean本身,則可以通過ApplicationContext的getBean(“&userFactoryBean”)。如果是通過類型擷取,就可以直接通過User類型或者UserFactoryBean類型擷取到對應的bean對象了。

(注:本文是基于Spring3.1.0所寫)