<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JAVA的SPI機(jī)制

          共 2615字,需瀏覽 6分鐘

           ·

          2021-01-28 15:41

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

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

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

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


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

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

          兩個(gè)實(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. 通過(guò)直接調(diào)用實(shí)現(xiàn)類的方式

          平常在開(kāi)發(fā)過(guò)程中 我們實(shí)例一個(gè)對(duì)象是通過(guò)new 的方式

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

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

          通過(guò)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
          ?}

          注意:

          通過(guò)SPI方式 我們需要提供一個(gè)特別的文件:

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

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

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

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

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

          在源碼中

          ServiceLoader類定義了一個(gè)前綴?

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

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

          SPI的應(yīng)用

          這里我們以JDBC為例子

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

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

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

          在SqlLite中 也有同樣的文件.

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


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

          其它的應(yīng)用:

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

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

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

          ...

          總結(jié)

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

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




          掃描二維碼

          獲取更多精彩

          JAVA寶典





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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线无码高清视频 | 色婷婷色婷婷色婷婷视频 | 亚洲色无码专区观看在线观 | 青草草在线 | 99热影院在线观看 |