工廠方法在Spring框架中的運(yùn)用
我們都知道Spring中IOC是使用的工廠模式,但是對(duì)于實(shí)現(xiàn)細(xì)節(jié)就一知半解了,今天這篇文章就帶大家解讀Spring中是如何使用工廠模式的。
在上篇文章中我們懂了什么是工廠模式,這篇文章就帶著學(xué)過的概念深入到Spring的內(nèi)部看看究竟是怎么使用該模式的。
在Spring中使用工廠方法的是BeanFactory和FactoryBean<>接口。
一、BeanFactory使用工廠方法
使用了Spring框架,我們就很少自己進(jìn)行對(duì)象的創(chuàng)建了,而我們使用到的對(duì)象當(dāng)然就是交給Spring的工廠模式來創(chuàng)建的了。
其中BeanFactory是Spring容器的頂層接口,也是Bean工廠最上層的接口,其會(huì)有很多工廠實(shí)現(xiàn)例如ClassPathXmlApplicationContext、XmlWebApplicationContext其中最常見的就是DefaultListableBeanFactory,我們可以把BeanFactory看成是一種工廠方法模式。
在工廠方法模式中有四個(gè)角色:
1、抽象工廠(Abstract Factory):提供了創(chuàng)建產(chǎn)品的接口,調(diào)用者通過它訪問具體工廠的工廠方法 createProduct() 來創(chuàng)建產(chǎn)品。
2、具體工廠(ConcreteFactory):主要是實(shí)現(xiàn)抽象工廠中的抽象方法,完成具體產(chǎn)品的創(chuàng)建。
3、抽象產(chǎn)品(Product):定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
4、具體產(chǎn)品(ConcreteProduct):實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口,由具體工廠來創(chuàng)建,它同具體工廠之間一一對(duì)應(yīng)。
BeanFactory是角色中的抽象工廠,而getBean就相當(dāng)于我們實(shí)例中的createProduct()方法,用于創(chuàng)建對(duì)象。
DefaultListableBeanFactory等實(shí)現(xiàn)的工廠類就是角色中的具體工廠。
產(chǎn)品就是在我們開發(fā)中加上注解的@Controller@Service@compent@Configuration的類,Spring會(huì)將他們當(dāng)成產(chǎn)品使用工廠模式生成對(duì)象。
在我們createProduct方法中是直接創(chuàng)建的對(duì)象,Spring肯定不會(huì)這么的笨,我們接著看getBean方法的實(shí)現(xiàn)方法。
getBean方法中一系列鏈路最終調(diào)用到doGetBean方法用于創(chuàng)建對(duì)象,在doGetBean中創(chuàng)建對(duì)象使用的是設(shè)計(jì)模式中的代理模式。
二、FactoryBean<>使用工廠方法
講完BeanFactory,再介紹另外一個(gè)工廠模式的應(yīng)用FactoryBean<>,想必大家也經(jīng)常會(huì)比較這倆。
實(shí)際上,這兩個(gè)接口都是用于創(chuàng)建對(duì)象,都可以看做是工廠方法模式的實(shí)現(xiàn)。
FactoryBean<>工廠通過getObject()方法來創(chuàng)建并返回對(duì)象,我們可以通過實(shí)現(xiàn)FactoryBean<>來定制化自己需要的Bean對(duì)象。
既然FactoryBean<>是留個(gè)開發(fā)者實(shí)現(xiàn)的,我們就手動(dòng)實(shí)現(xiàn)一個(gè)FactoryBean<>。
@Component
public class MyFactoryBean<> implements FactoryBean<><Product>, BeanNameAware {
private String name;
@Override
public Product getObject() throws Exception {
return new Product();
}
@Override
public Class<?> getObjectType() {
return Product.class;
}
@Override
public boolean isSingleton() {
return false;
}
@Override
public void setBeanName(String s) {
this.name = name;
}
}接著我們分別使用兩種方式getBean。
public static void main(String[] args) {
//測(cè)試FactoryBean<>
ApplicationContext ac =new AnnotationConfigApplicationContext(MyFactoryBean<>.class);
System.out.println(ac.getBean("myFactoryBean<>"));
System.out.println(ac.getBean("&myFactoryBean<>"));
}只是在獲取Bean時(shí)加了一個(gè)&會(huì)出現(xiàn)兩種情況。
cn.sky1998.create.methodFactory.Product@52a86356 cn.sky1998.create.methodFactory.MyFactoryBean<>@5ce81285
doGetBean里面進(jìn)行了判斷是否是FactoryBean<>的實(shí)現(xiàn)類。
Spring對(duì)FactoryBean<>的實(shí)現(xiàn)機(jī)制是當(dāng)你獲取一個(gè)Bean時(shí),如果獲取的Bean的類型是FactoryBean<>,并且其name中并沒有&則調(diào)用bean的getObject方法獲取FactoryBean<>實(shí)現(xiàn)類中提供bean,否則就是直接返回普通的bean類型。
當(dāng)我們?cè)谝肫渌蚣苷蟂pring時(shí),便會(huì)有很多橋接整合包,例如mybatis-spring等,其中就會(huì)有FactoryBean<>的實(shí)現(xiàn),例如SqlSessionFactoryBean<>、MapperFactoryBean<>等,將需要整合的定制化Bean通過工廠方法的模式,加入進(jìn)Spring容器中。
當(dāng)我們整合Mybatis時(shí)無(wú)論是多么的Bean都能很好的處理,mybatis-spring中的FactoryBean<>正是將Mybatis的核心啟動(dòng)類給調(diào)用出來。
三、BeanFactory和FactoryBean<>的異同
BeanFactory是Spring的一個(gè)大工廠,創(chuàng)建著Spring框架運(yùn)行過程中所需要的Bean;
而FactoryBean<>是一個(gè)定制化工廠,其會(huì)存在于BeanFactory創(chuàng)建對(duì)象的過程中,當(dāng)有需要時(shí),會(huì)通過FactoryBean<>去自定制個(gè)性化的Bean,從而Spring框架提高擴(kuò)展能力。
這篇文章加深工廠方法的理解的同時(shí),又進(jìn)一步的深入了BeanFactory和FactoryBean<>的實(shí)現(xiàn)細(xì)節(jié)。
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
- Springboot中實(shí)現(xiàn)策略模式+工廠模式的方法
- 使用SpringBoot 工廠模式自動(dòng)注入到Map
- 詳解Spring工廠特性
- 通過工廠模式返回Spring Bean方法解析
- Spring框架通過工廠創(chuàng)建Bean的三種方式實(shí)現(xiàn)
- Spring實(shí)戰(zhàn)之調(diào)用實(shí)例工廠方法創(chuàng)建Bean操作示例
- Spring實(shí)戰(zhàn)之使用靜態(tài)工廠方法創(chuàng)建Bean操作示例
- Spring的實(shí)例工廠方法和靜態(tài)工廠方法實(shí)例代碼
- Spring工廠方法創(chuàng)建(實(shí)例化)bean實(shí)例代碼
相關(guān)文章
使用Spring Boot創(chuàng)建Web應(yīng)用程序的示例代碼
本篇文章主要介紹了使用Spring Boot創(chuàng)建Web應(yīng)用程序的示例代碼,我們將使用Spring Boot構(gòu)建一個(gè)簡(jiǎn)單的Web應(yīng)用程序,并為其添加一些有用的服務(wù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
里氏代換原則_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了里氏代換原則的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
Springcloud服務(wù)注冊(cè)consul客戶端過程解析
這篇文章主要介紹了Springcloud服務(wù)注冊(cè)consul客戶端過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
Spring?Boot?使用斷言讓你的代碼在上線前就通過“體檢”(最新整理)
斷言是一種編程技巧,用于在代碼中插入檢查點(diǎn),驗(yàn)證程序的狀態(tài)是否符合預(yù)期,如果斷言失敗,程序會(huì)拋出一個(gè)錯(cuò)誤,幫助你快速發(fā)現(xiàn)和修復(fù)bug,本文給大家介紹Spring?Boot?斷言:讓你的代碼在上線前就通過“體檢”,感興趣的朋友一起看看吧2025-03-03
java 用遞歸獲取一個(gè)目錄下的所有文件路徑的小例子
還是日志的問題,log4j生成的日志文件,自動(dòng)保存到月份所在的文件夾中,需要獲取到所有的日志文件,包括文件夾2013-09-09
SpringCloud使用Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用的使用示例
Feign是一個(gè)基于注解的HTTP客戶端庫(kù),它允許您將HTTP請(qǐng)求轉(zhuǎn)換為聲明式的Java接口,本文主要介紹了SpringCloud使用Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用的使用示例,感興趣的可以了解一下2023-09-09



