最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Spring特性實(shí)現(xiàn)接口多實(shí)現(xiàn)類(lèi)的動(dòng)態(tài)調(diào)用方式

 更新時(shí)間:2022年02月25日 11:52:20   作者:EmineWang  
這篇文章主要介紹了使用Spring特性實(shí)現(xiàn)接口多實(shí)現(xiàn)類(lèi)的動(dòng)態(tài)調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

正好用到。mark一下背景

org.springframework.beans及org.springframework.context這兩個(gè)包是Spring IoC容器的基礎(chǔ),其中重要的類(lèi)有BeanFactory,BeanFactory是IoC容器的核心接口,其職責(zé)包括:實(shí)例化、定位、配置應(yīng)用程序中的對(duì)象及建立這些對(duì)象間的依賴關(guān)系。

ApplicationContext作為BeanFactory的子類(lèi),在Bean管理的功能上得到了很大的增強(qiáng),也更易于與Spring AOP集成使用。

今天我們要討論的并不是BeanFactory或者ApplicationContext的實(shí)現(xiàn)原理,而是對(duì)ApplicationContext的一種實(shí)際應(yīng)用方式。

問(wèn)題的提出

在實(shí)際工作中,我們經(jīng)常會(huì)遇到一個(gè)接口及多個(gè)實(shí)現(xiàn)類(lèi)的情況,并且在不同的條件下會(huì)使用不同的實(shí)現(xiàn)類(lèi)。

從使用方式上看,有些類(lèi)似SPI的用法,但是由于SPI的使用并不是太方便,那么怎么辦呢?我們可以借助ApplicationContext的getBeansOfType來(lái)實(shí)現(xiàn)我們需要的結(jié)果。

首先我們看一下這個(gè)方法的簽名

<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;

從上面的代碼上我們可以看出來(lái)這個(gè)方法能返回一個(gè)接口的全部實(shí)現(xiàn)類(lèi)(前提是所有實(shí)現(xiàn)類(lèi)都必須由Spring IoC容器管理)。

接下來(lái)看看我們遇到的問(wèn)題是什么?

"假設(shè)從A點(diǎn)到B點(diǎn)有多種交通方式,每種交通方式的費(fèi)用不同,可以根據(jù)乘客的需要進(jìn)行選擇"(好吧,我承認(rèn)這是個(gè)非常蹩腳的需求,但是可以聯(lián)想一下類(lèi)似的需求,比如支付方式、快遞公司,在頁(yè)面提供幾個(gè)選項(xiàng),業(yè)務(wù)代碼根據(jù)選項(xiàng)的不同選擇不同的實(shí)現(xiàn)類(lèi)實(shí)例進(jìn)行調(diào)用)。

實(shí)現(xiàn)

回到我們的例子,按照這個(gè)交通方式的需求,我們的設(shè)計(jì)如下:有一個(gè)交通方式的接口,接口有兩個(gè)方式,一個(gè)查詢費(fèi)用、一個(gè)查詢?cè)摻煌ǚ绞降念?lèi)型,同時(shí),我們可以用一個(gè)枚舉類(lèi)型類(lèi)標(biāo)識(shí)交通類(lèi)型。

我們還需要一個(gè)工廠類(lèi)來(lái)根據(jù)交通類(lèi)型標(biāo)識(shí)查找該交通類(lèi)型的Bean實(shí)例,從而使用該實(shí)例,獲得交通類(lèi)型的詳細(xì)信息及該交通類(lèi)型的操作。

代碼如下

接口:

/**
 * 交通方式
 */
public interface TrafficMode { 
    /**
     * 查詢交通方式編碼
     * @return 編碼
     */
    TrafficCode getCode();
 
    /**
     * 查詢交通方式的費(fèi)用,單位:分
     * @return 費(fèi)用
     */
    Integer getFee(); 
}

枚舉:

/**
 * 交通類(lèi)型枚舉
 */
public enum TrafficCode { 
    TRAIN,
    BUS 
}

接口有兩個(gè)實(shí)現(xiàn)類(lèi):

/**
 * 汽車(chē)方式
 */
@Component
public class BusMode implements TrafficMode { 
    @Override
    public TrafficCode getCode() {
        return TrafficCode.BUS;
    }
 
    @Override
    public Integer getFee() {
        return 10000;
    } 
}
/**
 * 火車(chē)方式
 */
@Component
public class TrainMode implements TrafficMode { 
    @Override
    public TrafficCode getCode() {
        return TrafficCode.TRAIN;
    }
 
    @Override
    public Integer getFee() {
        return 9000;
    } 
}

工廠類(lèi):

/**
 * 交通方式工廠類(lèi)
 */
@Component
public class TrafficModeFactory implements ApplicationContextAware { 
    private static Map<TrafficCode, TrafficMode> trafficBeanMap;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, TrafficMode> map = applicationContext.getBeansOfType(TrafficMode.class);
        trafficBeanMap = new HashMap<>();
        map.forEach((key, value) -> trafficBeanMap.put(value.getCode(), value));
    }
 
    public static <T extends TrafficMode> T getTrafficMode(TrafficCode code) {
        return (T)trafficBeanMap.get(code);
    } 
}

驗(yàn)證

有了上面的代碼之后,我們一起通過(guò)單元測(cè)試來(lái)看一下效果,單元測(cè)試代碼片段如下:

    @Test
    public void testGetTrafficMode() {
        TrafficMode mode = TrafficModeFactory.getTrafficMode(TrafficCode.BUS);
        Assert.assertEquals(mode.getFee().intValue(), 10000); 
        mode = TrafficModeFactory.getTrafficMode(TrafficCode.TRAIN);
        Assert.assertEquals(mode.getFee().intValue(), 9000);
    }

運(yùn)行之后的結(jié)果呢?必然是通過(guò)。

關(guān)于SPI

文章到這里,有同學(xué)可能會(huì)問(wèn):這和SPI有什么區(qū)別呢?SPI同樣也能實(shí)現(xiàn)同樣的功能啊。首先說(shuō)明一下,SPI是JDK自帶的功能,雖然歷史是比較久遠(yuǎn)的了,但是不代表它不好,而且有些場(chǎng)景非SPI不可(比如JDBC)。

我們明確一下SPI是什么以及它的設(shè)計(jì)是用來(lái)做什么的。SPI的全名為Service Provider Interface(服務(wù)提供接口),因?yàn)檫@個(gè)是針對(duì)廠商或者插件的。比較經(jīng)典的用法就是JDBC,java提供了標(biāo)準(zhǔn)的JDBC接口,每個(gè)數(shù)據(jù)庫(kù)廠商提供自己的數(shù)據(jù)庫(kù)驅(qū)動(dòng)實(shí)現(xiàn)。

下面是JDBC驅(qū)動(dòng)的接口

public interface Driver {
    Connection connect(String var1, Properties var2) throws SQLException; 
    boolean acceptsURL(String var1) throws SQLException; 
    DriverPropertyInfo[] getPropertyInfo(String var1, Properties var2) throws SQLException; 
    int getMajorVersion(); 
    int getMinorVersion(); 
    boolean jdbcCompliant(); 
    Logger getParentLogger() throws SQLFeatureNotSupportedException;
}

下面是MySQL的JDBC驅(qū)動(dòng)實(shí)現(xiàn)的SPI配置

關(guān)于SPI我們點(diǎn)到為止,這里只是要說(shuō)明SPI和我們前面例子中使用的AP具有不同的適用場(chǎng)景。

在前面的例子里,我們用的是什么呢?Spring的API,API的全稱為Application Programming Interface(應(yīng)用程序編程接口),在一個(gè)應(yīng)用內(nèi)部,使用API是非常便捷的方式,也是最直接的方式。

總結(jié)一下,就是編程中,我們使用API是最多的。當(dāng)然我們也會(huì)使用SPI(雖然我們不是嚴(yán)格意義上的廠商或者插件),使用SPI也是在特定場(chǎng)景下為了解決問(wèn)題的一種途徑。

關(guān)于SPI更多的內(nèi)容,以后在慢慢介紹吧。

【附】關(guān)于SPI的約定:當(dāng)服務(wù)的提供者,提供了服務(wù)接口的一種實(shí)現(xiàn)之后,在jar包的META-INF/services/目錄里同時(shí)創(chuàng)建一個(gè)以服務(wù)接口命名的文件。

該文件里就是實(shí)現(xiàn)該服務(wù)接口的具體實(shí)現(xiàn)類(lèi)。而當(dāng)外部程序裝配這個(gè)模塊的時(shí)候,就能通過(guò)該jar包META-INF/services/里的配置文件找到具體的實(shí)現(xiàn)類(lèi)名,并裝載實(shí)例化,完成模塊的注入。

基于這樣一個(gè)約定就能很好的找到服務(wù)接口的實(shí)現(xiàn)類(lèi),而不需要再代碼里制定。

jdk提供服務(wù)實(shí)現(xiàn)查找的一個(gè)工具類(lèi):java.util.ServiceLoader,通過(guò)其load方法,傳入接口便能獲得其實(shí)現(xiàn)類(lèi)。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MyBatis-Plus實(shí)現(xiàn)字段自動(dòng)填充功能的示例

    MyBatis-Plus實(shí)現(xiàn)字段自動(dòng)填充功能的示例

    本文主要介紹了MyBatis-Plus實(shí)現(xiàn)字段自動(dòng)填充功能的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Springboot接收前端的Json但是為null問(wèn)題

    Springboot接收前端的Json但是為null問(wèn)題

    這篇文章主要介紹了Springboot接收前端的Json但是為null問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教<BR>
    2024-05-05
  • java判斷http地址是否連通(示例代碼)

    java判斷http地址是否連通(示例代碼)

    這篇文章通過(guò)實(shí)例代碼給大家介紹了java判斷http地址是否連通,文末給大家補(bǔ)充知識(shí)點(diǎn)url.openconnection() 設(shè)置超時(shí)時(shí)間的方法,感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • jmeter中json提取器如何提取多個(gè)參數(shù)值

    jmeter中json提取器如何提取多個(gè)參數(shù)值

    關(guān)于jmeter中的正則表達(dá)式及json提取器可以提取響應(yīng)值,但是實(shí)際可以需要上個(gè)接口的多個(gè)響應(yīng)值,本文就詳細(xì)的介紹一下如何使用,感興趣的可以了解一下
    2021-11-11
  • Java中增強(qiáng)for循環(huán)在一維數(shù)組和二維數(shù)組中的使用方法

    Java中增強(qiáng)for循環(huán)在一維數(shù)組和二維數(shù)組中的使用方法

    下面小編就為大家?guī)?lái)一篇Java中增強(qiáng)for循環(huán)在一維數(shù)組和二維數(shù)組中的使用方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • Java詳解HashMap實(shí)現(xiàn)原理和源碼分析

    Java詳解HashMap實(shí)現(xiàn)原理和源碼分析

    這篇文章主要介紹了Java關(guān)于HashMap的實(shí)現(xiàn)原理并進(jìn)行源碼分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • MyBatis使用resultMap如何解決列名和屬性名不一致

    MyBatis使用resultMap如何解決列名和屬性名不一致

    這篇文章主要介紹了MyBatis使用resultMap如何解決列名和屬性名不一致的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java非遞歸實(shí)現(xiàn)刪除任意目錄的方法

    Java非遞歸實(shí)現(xiàn)刪除任意目錄的方法

    這篇文章主要為大家詳細(xì)介紹了Java非遞歸實(shí)現(xiàn)刪除任意目錄的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java爬蟲(chóng)抓取視頻網(wǎng)站下載鏈接

    Java爬蟲(chóng)抓取視頻網(wǎng)站下載鏈接

    本文是通過(guò)JAVA獲取優(yōu)酷、土豆、酷6、6間房等視頻,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • SpringBoot中使用@scheduled定時(shí)執(zhí)行任務(wù)的坑

    SpringBoot中使用@scheduled定時(shí)執(zhí)行任務(wù)的坑

    本文主要介紹了SpringBoot中使用@scheduled定時(shí)執(zhí)行任務(wù)的坑,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05

最新評(píng)論

香港| 内黄县| 乐安县| 郎溪县| 政和县| 肥西县| 山东省| 宝坻区| 闽清县| 玛沁县| 托里县| 精河县| 滨州市| 新营市| 新化县| 桃源县| 全州县| 黔东| 雷州市| 友谊县| 扎赉特旗| 曲阜市| 阜新市| 桦南县| 黑龙江省| 尉氏县| 南京市| 乐亭县| 咸阳市| 建湖县| 垣曲县| 福鼎市| 托里县| 乌鲁木齐市| 久治县| 穆棱市| 贵港市| 荔浦县| 清水河县| 南岸区| 沂源县|