1. Java/Spring/Dubbo三種SPI機(jī)制,誰更好?

        共 3767字,需瀏覽 8分鐘

         ·

        2022-06-02 11:16


        文章來源:https://c1n.cn/my8R6

        SPI 機(jī)制應(yīng)用在了大家項(xiàng)目中的很多地方,在很多框架中也有普遍應(yīng)用,只不過很多人并沒有感知。
        舉個(gè)例子,為什么我們?cè)陧?xiàng)目中引入 mysql-connector 的 jar 包,就可以直接連接 MySQL 數(shù)據(jù)庫(kù)了?

        本篇文章就來介紹一下 SPI,聊聊 Java 、Spring、Dubbo 中的 SPI 機(jī)制。

        SPI

        SPI ( Service Provider Interface),是一種服務(wù)發(fā)現(xiàn)機(jī)制。
        SPI 的本質(zhì)是將接口的實(shí)現(xiàn)類的全限定名配置在文件中,并由服務(wù)加載器讀取配置文件,加載對(duì)應(yīng)接口的實(shí)現(xiàn)類。這樣就可以在運(yùn)行時(shí),獲取接口的實(shí)現(xiàn)類。
        通過這一特性,我們可以給很容易的通過 SPI 機(jī)制為程序提供拓展功能。

        Java SPI

        Java SPI 機(jī)制:

        Java SPI 是“基于接口的編程+策略模式+配置文件”組合實(shí)現(xiàn)的動(dòng)態(tài)加載機(jī)制。
        設(shè)計(jì)一個(gè)接口,將接口的實(shí)現(xiàn)類寫在配置文件中,服務(wù)通過讀取配置文件來發(fā)現(xiàn)實(shí)現(xiàn)類,進(jìn)行加載實(shí)例化然后使用。
        配置文件路徑:classpath下的META-INF/services/
        配置文件名:接口的全限定名
        配置文件內(nèi)容:接口的實(shí)現(xiàn)類的全限定名
        應(yīng)用舉例:

        1、自定義接口

        //?接口
        public?interface?Superman?{
        ????void?introduce();
        }

        //?實(shí)現(xiàn)類1
        public?class?IronMan?implements?Superman{
        ????@Override
        ????public?void?introduce()?{
        ????????System.out.println("我是鋼鐵俠!");
        ????}
        }
        //?實(shí)現(xiàn)類2
        public?class?CaptainAmerica?implements?Superman?{
        ????@Override
        ????public?void?introduce()?{
        ????????System.out.println("我是美國(guó)隊(duì)長(zhǎng)!");
        ????}
        }

        配置文件:

        測(cè)試:

        public?static?void?main(String[]?args)?{
        ????ServiceLoader?serviceLoader?=?ServiceLoader.load(Superman.class);
        ????System.out.println("Java?SPI:");
        ????serviceLoader.forEach(Superman::introduce);
        }
        運(yùn)行結(jié)果:

        2、java.sql.Driver 接口

        MySQL 的實(shí)現(xiàn):

        看到這里,你應(yīng)該就知道開頭問題的答案了,mysql-connector 的 jar 包中正是通過 SPI 的方式實(shí)現(xiàn)了 java 的 Driver 接口,所以我們的服務(wù)可以在運(yùn)行時(shí)獲取到 mysql 的驅(qū)動(dòng)類,從而連接 mysql 。

        Java SPI 原理:

        Java SPI 的實(shí)現(xiàn)在 ServiceLoader 類:

        這里截取部分代碼,有興趣的同學(xué)自行閱讀。

        獲取prefix下的配置文件(包括 jar 包):

        Java SPI 總結(jié):

        Java SPI 機(jī)制:為某個(gè)接口發(fā)現(xiàn)/尋找服務(wù)實(shí)現(xiàn)的機(jī)制。

        優(yōu)點(diǎn):

        心思想:解耦,使得第三方服務(wù)模塊的裝配控制的邏輯與調(diào)用者的業(yè)務(wù)代碼分離。可以根據(jù)實(shí)際業(yè)務(wù)情況進(jìn)行使用或擴(kuò)展。

        缺點(diǎn):
        1、獲取接口的實(shí)現(xiàn)類的方式不靈活
        serviceLoader 只能通過 Iterator 形式遍歷獲取,不能根據(jù)參數(shù)獲取指定的某個(gè)實(shí)現(xiàn)類。

        2、資源浪費(fèi)

        serviceLoader 只能通過遍歷的方式將接口的實(shí)現(xiàn)類全部獲取、加載并實(shí)例化一遍。如果不想用某些實(shí)現(xiàn)類,它也被加載并實(shí)例化,造成浪費(fèi)。

        Spring?SPI

        與 JDK SPI 類似, 相對(duì)于 Java 的 SPI 的優(yōu)勢(shì)在于:
        Spring SPI 指定配置文件為 classpath 下的 META-INF/spring.factories,所有的拓展點(diǎn)配置放到一個(gè)文件中。
        配置文件內(nèi)容為 key-value 類型,key 為接口的全限定名, value 為實(shí)現(xiàn)類的全限定名,可以為多個(gè)。
        spring.factories 文件舉例:


        應(yīng)用舉例:

        以 dubbo 的使用舉例:

        為什么我們?cè)陧?xiàng)目中引入 dubbo jar 包,application.yml 中配置 registry,provider 等,就可以直接通過使用 dubbo 的 Service 注解和 Reference 注解來使用 dubbo 服務(wù)了?

        哪有什么歲月靜好,不過是有人替你負(fù)重前行?!柏?fù)重前行的人”就是 "dubbo-spring-boot-starter" ?。其實(shí)就是用到了 spring SPI :


        以 EnableAutoConfiguration 的實(shí)現(xiàn)類 DubboAutoConfiguration 為例:

        在 spring boot 啟動(dòng)過程中 ,在 SpringFactoriesLoader.loadFactoryNames(type, classLoader) ?這一步中會(huì)將 EnableAutoConfiguration 的實(shí)現(xiàn)類全部進(jìn)行加載、解析、初始化。

        在實(shí)例化 EnableAutoConfiguration 的實(shí)現(xiàn)類時(shí),會(huì)執(zhí)行實(shí)現(xiàn)類 dubboAutoConfiguration 中的具體邏輯,將 dubbo 服務(wù)啟動(dòng)并注冊(cè)到 spring 容器中。

        DubboAutoConfiguration的大概實(shí)現(xiàn):

        讀取配置文件中的配置項(xiàng)值(配置項(xiàng):DubboConfigConfiguration)生成多個(gè)配置 bean,掃描 dubbo @Service 和?@Reference 注解的類,生成對(duì)應(yīng)的 bean。

        其實(shí)在我們使用的第三方依賴包中,很多都使用了 Spring SPI,如 dubbo,mybatis,redisson 等等。

        Dubbo SPI

        dubbo的 Filter、Protocol、Cluster、LoadBalance 等都是通過 SPI 的方式進(jìn)行拓展加載的。

        特點(diǎn):

        1、dubbo SPI 為每個(gè)拓展點(diǎn)(接口)單獨(dú)設(shè)置一個(gè)文件,文件名為接口的全限定名。如org.apache.dubbo.rpc.Filter,org.apache.dubbo.rpc.Protocol,org.apache.dubbo.rpc.cluster.LoadBalance 等。

        dubbo SPI 配置文件舉例:


        2、支持"別名的概念“,可以通過別名獲取拓展點(diǎn)的某個(gè)實(shí)現(xiàn)。
        配置文件內(nèi)容是 key -value 類型,key 是別名,value 是實(shí)現(xiàn)類的全限定名。
        只使用指定的 filter ,就不會(huì)實(shí)例化其他 filter 。

        3、支持 Dubbo 內(nèi)部的依賴注入

        Dubbo IOC

        通過 setter 方法進(jìn)行依賴注入。Dubbo 首先會(huì)通過反射獲取到實(shí)例的所有方法,然后再遍歷方法列表,檢測(cè)方法名是否具有 setter 方法特征。若有,則通過 ObjectFactory 獲取依賴對(duì)象,最后通過反射調(diào)用 setter 方法將依賴設(shè)置到目標(biāo)對(duì)象中。

        實(shí)現(xiàn):
        dubbo SPI 的實(shí)現(xiàn)在 ExtensionLoader 這個(gè)類。
        以獲取所有的 dubbo Filter 為例:
        1、首先獲取 Filter 的 ExtensionLoader

        ExtensionLoader.getExtensionLoader(Filter.class)

        2、由 ExtensionLoader 從配置文件中加載所有的拓展類

        加載項(xiàng)目中及 jar 包下以下目錄的配置文件:

        配置文件名為接口的全限定名。

        3、讀取配置文件時(shí),根據(jù) ’=‘ 為界限,確認(rèn)鍵值對(duì)。

        由此得到“配置項(xiàng)名稱”到“配置類”的映射關(guān)系表

        4、過程中多處使用緩存提升性能。

        緩存拓展類對(duì)應(yīng)的 ExtensionLoader 等。

        獲取到 別名 – 實(shí)現(xiàn)類的全限定名后,即可直接通過別名去獲取指定的拓展類。?

        Java、Spring、Dubbo?SPI 對(duì)比


        • —————END—————

        PS:如果覺得我的分享不錯(cuò),歡迎大家隨手點(diǎn)贊、在看。

        ?關(guān)注公眾號(hào):Java后端編程,回復(fù)下面關(guān)鍵字?


        要Java學(xué)習(xí)完整路線,回復(fù)??路線?

        缺Java入門視頻,回復(fù)?視頻?

        要Java面試經(jīng)驗(yàn),回復(fù)??面試?

        缺Java項(xiàng)目,回復(fù):?項(xiàng)目?

        進(jìn)Java粉絲群:?加群?


        PS:如果覺得我的分享不錯(cuò),歡迎大家隨手點(diǎn)贊、在看。

        (完)




        加我"微信"?獲取一份 最新Java面試題資料

        請(qǐng)備注:666不然不通過~


        最近好文


        1、必須推薦的一個(gè)后臺(tái)管理系統(tǒng)

        2、無意中發(fā)現(xiàn)了一位清華妹子的資料庫(kù)!

        3、Java后端編程讀者群正式成立了!

        4、一套簡(jiǎn)單通用的Java后臺(tái)管理系統(tǒng),拿來即用

        5、36 張圖梳理 Intellij IDEA 常用設(shè)置



        最近面試BAT,整理一份面試資料Java面試BAT通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。
        獲取方式:關(guān)注公眾號(hào)并回復(fù)?java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
        明天見(??ω??)??

        瀏覽 44
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 人人爽av | 豆花视频在线观看免费 | 又粗又硬视频 | 日本一级黄色视频 | 午夜精品一区二区三区视频 |