FactoryBean?BeanFactory方法使用示例詳解講解
一、FactoryBean:用來(lái)自定義Bean的創(chuàng)建邏輯
FactoryBean是接口,是為IOC容器中的Bean的實(shí)現(xiàn)提供了更加靈活的方式,F(xiàn)actoryBean在IOC容器的基礎(chǔ)上,給Bean的實(shí)現(xiàn)加上了一個(gè)簡(jiǎn)單工廠模式和裝飾模式。一般情況下實(shí)例化一個(gè)Bean對(duì)象:Spring通過(guò)反射機(jī)制利用bean的class屬性指定實(shí)現(xiàn)類(lèi)實(shí)例化Bean;在某些情況下,實(shí)例化Bean過(guò)程比較復(fù)雜,如果按照傳統(tǒng)的方式,則需要在bean中提供大量的配置信息。配置方式的靈活性是受限的,這時(shí)采用編碼的方式可能會(huì)得到一個(gè)簡(jiǎn)單的方案。
Spring為此提供了一個(gè)org.springframework.bean.factory.FactoryBean的工廠類(lèi)接口,用戶可以通過(guò)實(shí)現(xiàn)該接口, 然后在getObject()方法中靈活配置,來(lái)定制實(shí)例化Bean的邏輯。FactoryBean接口對(duì)于Spring框架來(lái)說(shuō)占用重要的地位,Spring自身就提供了70多個(gè)FactoryBean的實(shí)現(xiàn)——(xxxFactoryBean)。它們隱藏了實(shí)例化一些復(fù)雜Bean的細(xì)節(jié),給上層應(yīng)用帶來(lái)了便利。從Spring3.0開(kāi)始,F(xiàn)actoryBean開(kāi)始支持泛型,即接口聲明改為FactoryBean的形式。從BeanFactory及其實(shí)現(xiàn)類(lèi)的getBean() 方法中獲取到的Bean對(duì)象,實(shí)際上是FactoryBean的getObject()方法創(chuàng)建并返回的Bean對(duì)象,而不是FactoryBean本身。
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
方法一:getObject():返回Bean對(duì)象;
方法二,getObjectType() :返回的Bean對(duì)象的類(lèi)型;
方法三,isSingleton() :是否是單例對(duì)象,true是單例,false是非單例;
實(shí)現(xiàn)SqlSessionFactoryBean:
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent>
定義TestBean實(shí)現(xiàn)FactoryBean接口并實(shí)現(xiàn)getObject()和getObjectType()方法,其中在getObject()方法中實(shí)例化一個(gè)TestBean對(duì)象,并對(duì)message進(jìn)行了一些特殊處理(區(qū)別于構(gòu)造方法)。
@Component
public class TestBean implements FactoryBean {
private String message;
public TestBean() {
this.message = "通過(guò)構(gòu)造方法初始化實(shí)例";
}
@Override
public Object getObject() throws Exception {
TestBean testBean = new TestBean();
testBean.message = "通過(guò)FactoryBean.getObject()創(chuàng)建實(shí)例";
// 這里并不一定要返回TestBean自身的實(shí)例,可以是其他任何對(duì)象的實(shí)例
return testBean;
}
@Override
public Class<?> getObjectType() {
return TestBean.class;
}
public String getMessage() {
return message;
}
}
TestBean測(cè)試類(lèi):
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class FactoryBeanTest {
@Autowired
private ApplicationContext context;
@Test
public void test() {
TestBean myBean1 = (TestBean) context.getBean("testBean");
System.out.println("myBean1 = " + myBean1.getMessage());
TestBean myBean2 = (TestBean) context.getBean("&testBean");
System.out.println("myBean2 = " + myBean2.getMessage());
System.out.println("myBean1.equals(myBean2) = " + myBean1.equals(myBean2));
}
}
輸出結(jié)果:
myBean1 = 通過(guò)FactoryBean.getObject()初始化實(shí)例
myBean2 = 通過(guò)構(gòu)造方法初始化實(shí)例
myBean1.equals(myBean2) = false
結(jié)論:
可見(jiàn)當(dāng)調(diào)用getBean("testBean")時(shí),Spring通過(guò)反射機(jī)制發(fā)現(xiàn)TestBean實(shí)現(xiàn)了FactoryBean接口,這時(shí)Spring容器就調(diào)用接口方法TestBean#getObject()方法返回,這時(shí)返回的并不是FactoryBean本身,而是FactoryBean#getObject()方法內(nèi)部所返回的對(duì)象TestBean,相當(dāng)于FactoryBean#getObject()代理了getBean() 方法。如果希望獲取TestBean的實(shí)例,則需要在使用getBean(beanName)方法時(shí)在beanName前顯示的加上 "&"前綴,如getBean("&testBean")。
當(dāng)通過(guò)getBean()方法獲取到一個(gè)Bean時(shí),返回的并不是xxxFactoryBean本身,而是其創(chuàng)建的Bean對(duì)象; 如果要獲取xxxFactoryBean對(duì)象本身,請(qǐng)?jiān)趨?shù)前面加一個(gè)&符號(hào)來(lái)獲取,即:getBean(&BeanName)
二、BeanFactory:負(fù)責(zé)生產(chǎn)和管理bean的一個(gè)工廠類(lèi)頂層接口
BeanFactory是一個(gè)負(fù)責(zé)生產(chǎn)和管理bean的一個(gè)工廠類(lèi)(接口)。在Spring中,BeanFactory是IOC容器的核心接口,它的職責(zé)包括:實(shí)例化、定位、配置應(yīng)用程序中的對(duì)象及建立這些對(duì)象間的依賴。我們通過(guò)getBean()方法,傳入?yún)?shù)——bean的名稱(chēng)或者類(lèi)型,便可以從Spring容器中來(lái)獲取bean。
BeanFactory是用于訪問(wèn)Spring容器的根接口,是從Spring容器中獲取Bean對(duì)象的基礎(chǔ)接口,提供了IOC容器最基本的形式,給具體的IOC容器的實(shí)現(xiàn)提供了規(guī)范。BeanFactory只是個(gè)接口,并不是IOC容器的具體實(shí)現(xiàn),Spring容器給出了很多種 BeanFactory的 擴(kuò)展實(shí)現(xiàn),如:DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等。

從類(lèi)圖中可以看出,我們更常用的ApplicationContext就是一個(gè)BeanFactory。ApplicationContext接口由BeanFactory接口派生而來(lái),ApplicationContext包含BeanFactory的所有功能,還提供了以下更多的功能:
1、MessageSource, 提供國(guó)際化的消息訪問(wèn) ;
2、資源訪問(wèn),如URL和文件;
3、事件傳播。
相比BeanFactory,通常建議優(yōu)先使用ApplicationContext。
BeanFactory的一些是實(shí)現(xiàn),除了ApplicationContext,還有很多,例如:
AbstractBeanFactory:抽象Bean工廠,絕大部分的實(shí)現(xiàn)類(lèi),都是繼承于他DefaultListableBeanFactory:Spring默認(rèn)的工廠類(lèi)XmlBeanFactory:前期使用XML配置用的比較多的時(shí)候用的Bean工廠AbstractXmlApplicationContext:抽象應(yīng)用容器上下文對(duì)象ClassPathXmlApplicationContext:XML解析上下文對(duì)象,用戶創(chuàng)建Bean對(duì)象我們?cè)缙趯?xiě)Spring的時(shí)候用它
三、FactoryBean與BeanFactory區(qū)別
BeanFactory是個(gè)Factory,也就是IOC容器或?qū)ο蠊S,F(xiàn)actoryBean是個(gè)Bean。 在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)來(lái)進(jìn)行管理的。但對(duì)FactoryBean而言,這個(gè)Bean不是簡(jiǎn)單的Bean,而是一個(gè)能生產(chǎn)或者修飾對(duì)象生成的工廠Bean,它的實(shí)現(xiàn)與設(shè)計(jì)模式中的工廠模式和修飾器模式類(lèi)似。
以上就是FactoryBean BeanFactory方法使用示例詳解講解的詳細(xì)內(nèi)容,更多關(guān)于FactoryBean BeanFactory方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
運(yùn)用Spring?Aop+注解實(shí)現(xiàn)日志記錄
我們都知道Spring框架的兩大特性分別是 IOC (控制反轉(zhuǎn))和 AOP (面向切面),這個(gè)是每一個(gè)Spring學(xué)習(xí)視頻里面一開(kāi)始都會(huì)提到的,這里,如果我們使用Aop來(lái)記錄日志,那是再好不過(guò)了,感興趣的朋友跟隨小編一起學(xué)習(xí)下Spring?Aop注解實(shí)現(xiàn)日志記錄的過(guò)程吧2022-01-01
java虛擬機(jī)深入學(xué)習(xí)之內(nèi)存管理機(jī)制
java虛擬機(jī)在程序運(yùn)行時(shí)將內(nèi)存劃分為多個(gè)區(qū)域,每個(gè)區(qū)域作用,生命周期各不相同,下面這篇文章主要給大家介紹了關(guān)于java虛擬機(jī)深入學(xué)習(xí)之內(nèi)存管理機(jī)制的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-11-11
springboot啟動(dòng)掃描不到dao層接口的解決方案
這篇文章主要介紹了springboot啟動(dòng)掃描不到dao層接口的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Mybatis插件之自動(dòng)生成不使用默認(rèn)的駝峰式操作
這篇文章主要介紹了Mybatis插件之自動(dòng)生成不使用默認(rèn)的駝峰式操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
Java通過(guò)Lambda表達(dá)式實(shí)現(xiàn)簡(jiǎn)化代碼
我們?cè)诰帉?xiě)代碼時(shí),常常會(huì)遇到代碼又長(zhǎng)又重復(fù)的情況,就像調(diào)用第3方服務(wù)時(shí),每個(gè)方法都差不多,?寫(xiě)起來(lái)啰嗦,?改起來(lái)麻煩,?還容易改漏,所以本文就來(lái)用Lambda表達(dá)式簡(jiǎn)化一下代碼,希望對(duì)大家有所幫助2023-05-05
SpringBoot之HandlerInterceptor攔截器的使用詳解
這篇文章主要介紹了SpringBoot之HandlerInterceptor攔截器的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10

