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

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

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

正好用到。mark一下背景

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

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

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

問題的提出

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

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

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

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

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

接下來看看我們遇到的問題是什么?

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

實(shí)現(xiàn)

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

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

代碼如下

接口:

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

枚舉:

/**
 * 交通類型枚舉
 */
public enum TrafficCode { 
    TRAIN,
    BUS 
}

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

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

工廠類:

/**
 * 交通方式工廠類
 */
@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)證

有了上面的代碼之后,我們一起通過單元測(cè)試來看一下效果,單元測(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ān)于SPI

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

我們明確一下SPI是什么以及它的設(shè)計(jì)是用來做什么的。SPI的全名為Service Provider Interface(服務(wù)提供接口),因?yàn)檫@個(gè)是針對(duì)廠商或者插件的。比較經(jīng)典的用法就是JDBC,java提供了標(biāo)準(zhǔn)的JDBC接口,每個(gè)數(shù)據(jù)庫廠商提供自己的數(shù)據(jù)庫驅(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)到為止,這里只是要說明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)景下為了解決問題的一種途徑。

關(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)類。而當(dāng)外部程序裝配這個(gè)模塊的時(shí)候,就能通過該jar包META-INF/services/里的配置文件找到具體的實(shí)現(xiàn)類名,并裝載實(shí)例化,完成模塊的注入。

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

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

以上為個(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)填充功能的示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Springboot接收前端的Json但是為null問題

    Springboot接收前端的Json但是為null問題

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

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

    這篇文章通過實(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ī)硪黄狫ava中增強(qiáng)for循環(huán)在一維數(shù)組和二維數(shù)組中的使用方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    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如何解決列名和屬性名不一致的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java非遞歸實(shí)現(xiàn)刪除任意目錄的方法

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

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

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

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

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

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

最新評(píng)論

海丰县| 大邑县| 会昌县| 娄底市| 龙井市| 吉水县| 乌鲁木齐市| 定远县| 高邑县| 夏邑县| 临沂市| 绥中县| 蒙阴县| 五原县| 孟连| 香格里拉县| 台北市| 宜兴市| 武冈市| 宜黄县| 天长市| 陕西省| 黄冈市| 惠来县| 通江县| 浦东新区| 亳州市| 金乡县| 信丰县| 水城县| 望都县| 昭觉县| 静海县| 南部县| 霍邱县| 桦南县| 余干县| 景泰县| 长白| 罗甸县| 喀喇沁旗|