1. JAVA的SPI機(jī)制

        共 2615字,需瀏覽 6分鐘

         ·

        2021-01-28 15:41

        JAVA的SPI機(jī)制是什么?

        SPI(Service Provider Interface): ,“服務(wù)提供者接口”,是指在 服務(wù)使用方 角度提出的“接口要求”,是對“服務(wù)提供方”提出的約定,簡單說就是:“我需要這樣的服務(wù),現(xiàn)在你們來滿足”。

        是不是看起來很高深的樣子.其實(shí)特別簡單 我們先來一個例子,大家更容易理解什么是JAVA的SPI機(jī)制:

        首先我們提供了一個訂單處理的接口


        /**
        ?*?@Author:?lty
        ?*?@Date:?2021/1/22?14:24
        ?*?訂單的處理接口
        ?*/

        public?interface?OrderHandlerService?{
        ????String??handler(String?orderid);
        }

        兩個實(shí)現(xiàn)類


        public?class?PddOrderHandler?implements?OrderHandlerService
        {
        ????@Override
        ????public?String?handler(String?orderid)?{
        ????????System.out.println("Pdd?handler?execute");
        ????????return?"Pdd?handler?execute";
        ????}
        }


        public?class?TaobaoOrderHandler?implements?OrderHandlerService
        {
        ????@Override
        ????public?String?handler(String?orderid)?{
        ????????System.out.println("taobao?handler?execute");
        ????????return?"taobao?handler?execute";
        ????}
        }

        類圖關(guān)系:



        1. 通過直接調(diào)用實(shí)現(xiàn)類的方式

        平常在開發(fā)過程中 我們實(shí)例一個對象是通過new 的方式

        public?static?void?main(String[]?args)?{
        ????????OrderHandlerService?pddOrderHandler?=?new?PddOrderHandler();
        ????????pddOrderHandler.handler("000000001");
        }
        ????????
        //Pdd?handler?execute

        2. 通過SPI 提供實(shí)現(xiàn)類的方式

        通過ServiceLoader.load()方法獲取實(shí)現(xiàn)類

        public?static?void?main(String[]?args)?{
        ????????//使用spi
        ????????ServiceLoader?services?=?ServiceLoader.load(OrderHandlerService.class);
        ????????services.forEach(orderHandlerService?->?{
        ????????????orderHandlerService.handler("000001");
        ????????});
        ????????
        ????????//Pdd?handler?execute
        ????????//taobao?handler?execute
        ?}

        注意:

        通過SPI方式 我們需要提供一個特別的文件:

        文件位于 /resources/META-INF/services

        文件名為 com.xxx. 即接口的全限定名稱。

        內(nèi)容為兩個實(shí)現(xiàn)類的全限定名稱:

        com.liangtengyu.service.Impl.PddOrderHandler
        com.liangtengyu.service.Impl.TaobaoOrderHandler

        具體的底層實(shí)現(xiàn)可以分離出來 實(shí)現(xiàn)外部加載,也可以將每組實(shí)現(xiàn)和SPI配置文件打包成不同的jar,在具體使用時根據(jù)需要使用不同的jar即可。

        在源碼中

        ServiceLoader類定義了一個前綴?

        private static final String PREFIX = "META-INF/services/"

        用來約定上述指定的位置,基于約定的配置讀取會從這里查找,如果我們引入了第三方的jar包,如果jar中的META-INF/service有OrderHandlerService的實(shí)現(xiàn),也會被讀取,并且實(shí)例化里面的類。

        SPI的應(yīng)用

        這里我們以JDBC為例子

        mysql-connector-java:5.1.32 包的 META-INF/services/ 目錄下有個 java.sql.Driver

        文件,內(nèi)容為:

        com.mysql.jdbc.Driver
        com.mysql.fabric.jdbc.FabricMySQLDriver

        在SqlLite中 也有同樣的文件.

        它們都是用來加載實(shí)現(xiàn)了java.sql.Driver接口實(shí)現(xiàn)類的位置


        //內(nèi)容為
        org.sqlite.JDBC

        其它的應(yīng)用:

        日志門面接口實(shí)現(xiàn)類加載,SLF4J加載不同提供商的日志實(shí)現(xiàn)類

        Spring中大量使用了SPI,比如:對servlet3.0規(guī)范對ServletContainerInitializer的實(shí)現(xiàn)、自動類型轉(zhuǎn)換Type Conversion SPI(Converter SPI、Formatter SPI)等

        Dubbo中也大量使用SPI的方式實(shí)現(xiàn)框架的擴(kuò)展, 不過它對Java提供的原生SPI做了封裝,允許用戶擴(kuò)展實(shí)現(xiàn)Filter接口

        ...

        總結(jié)

        優(yōu)點(diǎn):使用Java SPI機(jī)制的優(yōu)勢是實(shí)現(xiàn)解耦,使得第三方服務(wù)模塊的裝配控制的邏輯與調(diào)用者的業(yè)務(wù)代碼分離,而不是耦合在一起。應(yīng)用程序可以根據(jù)實(shí)際業(yè)務(wù)情況啟用框架擴(kuò)展或替換框架組件。

        缺點(diǎn):雖然ServiceLoader也算是使用的延遲加載,但是基本只能通過遍歷全部獲取,也就是接口的實(shí)現(xiàn)類全部加載并實(shí)例化一遍。如果你并不想用某些實(shí)現(xiàn)類,它也被加載并實(shí)例化了,這就造成了浪費(fèi)。獲取某個實(shí)現(xiàn)類,的方式不夠靈活,多個并發(fā)多線程使用ServiceLoader類的實(shí)例是不安全的。




        掃描二維碼

        獲取更多精彩

        JAVA寶典





        瀏覽 53
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 人人干人人操人人色91 | SESE男人的天堂 | 欧美性折磨bdsm另类 | 好硬好深操我啊啊 | 一级片俄罗斯 |