您好,登錄后才能下訂單哦!
小編給大家分享一下Spring中BeanFactory與FactoryBean有什么區(qū)別,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
在Spring中有BeanFactory和FactoryBean這2個(gè)接口,從名字來(lái)看很相似,比較容易搞混。
BeanFactory
是一個(gè)接口,它是Spring中工廠的頂層規(guī)范,是SpringIoc容器的核心接口,它定義了getBean()
、containsBean()
等管理Bean的通用方法。Spring的容器都是它的具體實(shí)現(xiàn)如:
DefaultListableBeanFactory
XmlBeanFactory
ApplicationContext
這些實(shí)現(xiàn)類又從不同的維度分別有不同的擴(kuò)展。
public interface BeanFactory { //對(duì)FactoryBean的轉(zhuǎn)義定義,因?yàn)槿绻褂胋ean的名字檢索FactoryBean得到的對(duì)象是工廠生成的對(duì)象, //如果需要得到工廠本身,需要轉(zhuǎn)義 String FACTORY_BEAN_PREFIX = "&"; //根據(jù)bean的名字,獲取在IOC容器中得到bean實(shí)例 Object getBean(String name) throws BeansException; //根據(jù)bean的名字和Class類型來(lái)得到bean實(shí)例,增加了類型安全驗(yàn)證機(jī)制。 <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; //提供對(duì)bean的檢索,看看是否在IOC容器有這個(gè)名字的bean boolean containsBean(String name); //根據(jù)bean名字得到bean實(shí)例,并同時(shí)判斷這個(gè)bean是不是單例 boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException; //得到bean實(shí)例的Class類型 @Nullable Class<?> getType(String name) throws NoSuchBeanDefinitionException; //得到bean的別名,如果根據(jù)別名檢索,那么其原名也會(huì)被檢索出來(lái) String[] getAliases(String name); }
從Ioc容器中獲取Bean(byName or byType)
檢索Ioc容器中是否包含指定的Bean
判斷Bean是否為單例
首先它是一個(gè)Bean,但又不僅僅是一個(gè)Bean。它是一個(gè)能生產(chǎn)或修飾對(duì)象生成的工廠Bean,類似于設(shè)計(jì)模式中的工廠模式和裝飾器模式。它能在需要的時(shí)候生產(chǎn)一個(gè)對(duì)象,且不僅僅限于它自身,它能返回任何Bean的實(shí)例。
public interface FactoryBean<T> { //從工廠中獲取bean @Nullable T getObject() throws Exception; //獲取Bean工廠創(chuàng)建的對(duì)象的類型 @Nullable Class<?> getObjectType(); //Bean工廠創(chuàng)建的對(duì)象是否是單例模式 default boolean isSingleton() { return true; } }
從它定義的接口可以看出,FactoryBean
表現(xiàn)的是一個(gè)工廠的職責(zé)。 即一個(gè)Bean A如果實(shí)現(xiàn)了FactoryBean接口,那么A就變成了一個(gè)工廠,根據(jù)A的名稱獲取到的實(shí)際上是工廠調(diào)用getObject()
返回的對(duì)象,而不是A本身,如果要獲取工廠A自身的實(shí)例,那么需要在名稱前面加上'&
'符號(hào)。
getObject('name')返回工廠中的實(shí)例
getObject('&name')返回工廠本身的實(shí)例
通常情況下,bean 無(wú)須自己實(shí)現(xiàn)工廠模式,Spring 容器擔(dān)任了工廠的 角色;但少數(shù)情況下,容器中的 bean 本身就是工廠,作用是產(chǎn)生其他 bean 實(shí)例。由工廠 bean 產(chǎn)生的其他 bean 實(shí)例,不再由 Spring 容器產(chǎn)生,因此與普通 bean 的配置不同,不再需要提供 class 元素。
先定義一個(gè)Bean實(shí)現(xiàn)FactoryBean接口
@Component public class MyBean implements FactoryBean { private String message; public MyBean() { this.message = "通過(guò)構(gòu)造方法初始化實(shí)例"; } @Override public Object getObject() throws Exception { // 這里并不一定要返回MyBean自身的實(shí)例,可以是其他任何對(duì)象的實(shí)例。 //如return new Student()... return new MyBean("通過(guò)FactoryBean.getObject()創(chuàng)建實(shí)例"); } @Override public Class<?> getObjectType() { return MyBean.class; } public String getMessage() { return message; } }
MyBean實(shí)現(xiàn)了FactoryBean接口的兩個(gè)方法,getObject()是可以返回任何對(duì)象的實(shí)例的,這里測(cè)試就返回MyBean自身實(shí)例,且返回前給message字段賦值。同時(shí)在構(gòu)造方法中也為message賦值。然后測(cè)試代碼中先通過(guò)名稱獲取Bean實(shí)例,打印message的內(nèi)容,再通過(guò)&+名稱
獲取實(shí)例并打印message內(nèi)容。
@RunWith(SpringRunner.class) @SpringBootTest(classes = TestApplication.class) public class FactoryBeanTest { @Autowired private ApplicationContext context; @Test public void test() { MyBean myBean1 = (MyBean) context.getBean("myBean"); 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 = 通過(guò)FactoryBean.getObject()初始化實(shí)例 myBean2 = 通過(guò)構(gòu)造方法初始化實(shí)例 myBean1.equals(myBean2) = false
說(shuō)了這么多,為什么要有FactoryBean
這個(gè)東西呢,有什么具體的作用嗎?
FactoryBean在Spring中最為典型的一個(gè)應(yīng)用就是用來(lái)創(chuàng)建AOP的代理對(duì)象。
我們知道AOP實(shí)際上是Spring在運(yùn)行時(shí)創(chuàng)建了一個(gè)代理對(duì)象,也就是說(shuō)這個(gè)對(duì)象,是我們?cè)谶\(yùn)行時(shí)創(chuàng)建的,而不是一開(kāi)始就定義好的,這很符合工廠方法模式。更形象地說(shuō),AOP代理對(duì)象通過(guò)Java的反射機(jī)制,在運(yùn)行時(shí)創(chuàng)建了一個(gè)代理對(duì)象,在代理對(duì)象的目標(biāo)方法中根據(jù)業(yè)務(wù)要求織入了相應(yīng)的方法。這個(gè)對(duì)象在Spring中就是——ProxyFactoryBean
。
所以,F(xiàn)actoryBean為我們實(shí)例化Bean提供了一個(gè)更為靈活的方式,我們可以通過(guò)FactoryBean創(chuàng)建出更為復(fù)雜的Bean實(shí)例。
他們兩個(gè)都是個(gè)工廠,但FactoryBean
本質(zhì)上還是一個(gè)Bean,也歸BeanFactory
管理
BeanFactory
是Spring容器的頂層接口,FactoryBean
更類似于用戶自定義的工廠接口。
BeanFactory
與FactoryBean
的區(qū)別確實(shí)容易混淆,死記硬背是不行的,最好還是從源碼層面,置于spring的環(huán)境中去理解。
看完了這篇文章,相信你對(duì)“Spring中BeanFactory與FactoryBean有什么區(qū)別”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。