<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java SPI詳解

      SPI的英文全稱為Service Provider Interface,字面意思為服務提供者接口,它是jdk提供給“服務提供廠商”或者“插件開發者”使用的接口。

      在面向對象的設計中,模塊之間我們一般會采取面向接口編程的方式,而在實際編程過程過程中,API的實現是封裝在jar中,當我們想要換一種實現方法時,還要生成新的jar替換以前的實現類。而通過jdk的SPI機制就可以實現,首先不需要修改原來作為接口的jar的情況下,將原來實現的那個jar替換為另外一種實現的jar即可。

      總結一下SPI的思想:在系統的各個模塊中,往往有不同的實現方案,例如日志模塊的方案、xml解析的方案等,為了在裝載模塊的時候不具體指明實現類,我們需要一種服務發現機制,java spi就提供這樣一種機制。有點類似于IoC的思想,將服務裝配的控制權移到程序之外,在模塊化設計時尤其重要。

      順便提一下,Java SPI機制在很多大型中間件嗎,例如Dubbo中均有采用,屬于高級Java開發的進階必備知識點,務必要求掌握。

      一. SPI規范

      定義服務的通用接口,針對通用的服務接口,提供具體的實現類。

      1. 在jar包(服務提供者)的META-INF/services/目錄中,新建一個文件,文件名為SPI接口的"全限定名"。 文件內容為該接口的具體實現類的"全限定名"

      2. 將spi所在jar放在主程序的classpath中

      3. 服務調用方使用java.util.ServiceLoader去動態加載具體的實現類到JVM中

      二. SPI應用案例

      2.1 數據庫驅動

      java.sql.Driver的spi實現,有mysql驅動、oracle驅動等。以mysql為例,實現類是com.mysql.jdbc.Driver,在mysql-connector-java-5.1.6.jar中,我們可以看到有一個META-INF/services目錄,目錄下有一個文件名為java.sql.Driver的文件,其中的內容是com.mysql.jdbc.Driver。

      在我們使用JDBC獲取連接時,我們通常會調用DriverManager.getConnection()方法獲取連接對象,而在Driver類初始化時會使用ServiceLoader動態獲取classpath下“注冊”的驅動實現:

      static {
              loadInitialDrivers();
              println("JDBC DriverManager initialized");
      }
      
      private static void loadInitialDrivers() {
              .....
              AccessController.doPrivileged(new PrivilegedAction<Void>() {
                  public Void run() {
      				//使用ServiceLoader動態加載具體的驅動實現類
                      ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
                      Iterator<Driver> driversIterator = loadedDrivers.iterator();
                      try{
                          while(driversIterator.hasNext()) {
                              driversIterator.next();
                          }
                      } catch(Throwable t) {
                      // Do nothing
                      }
                      return null;
                  }
              });
      		.....
          }
      

      2.2 Slf4j

      slf4j是一個典型的門面接口,早起我們使用log4j作為日記記錄框架,我們需要同時引入slf4j和log4j的依賴。后面比較流行logback,我們也想要把項目切換到logback上來,此時利用SPI的機制,我們只需要把log4j的jar包替換為logback的jar包就可以了。

      log4j-to-slf4j.jar中我們可以看到前面提到的服務提供方的SPI接口聲明

      這樣我們只需要將log4j-to-slf4j.jar引入classpath,slf4j就能夠獲取到org.apache.logging.slf4j.SLF4JProvider作為實現類。

      三. SPI示例

      模塊依賴關系:

      3.1 spi-operate-service模塊

      spi-operate-service中定義INumOperate接口:

      package cn.bigcoder.spi.operate.service;
      
      /**
       * @author: Jindong.Tian
       * @date: 2020-11-29
       * @description:
       **/
      public interface INumOperate {
      
          int exec(int num1, int num2);
      }
      

      3.2 spi-operate-add模塊

      spi-operate-add中定義加法實現:

      package cn.bigcoder.spi.operate.add;
      
      
      import cn.bigcoder.spi.operate.service.INumOperate;
      
      /**
       * @author: Jindong.Tian
       * @date: 2020-11-29
       * @description:
       **/
      public class NumAddOperateImpl implements INumOperate {
      
          public int exec(int num1, int num2) {
              return num1 + num2;
          }
      }
      

      resource/METAINF/resoures目錄下創建cn.bigcoder.spi.operate.service.INumOperate文件:

      cn.bigcoder.spi.operate.add.NumAddOperateImpl
      

      3.3 spi-operate-multiplication模塊

      spi-operate-multiplication模塊中定義乘法的實現:

      package cn.bigcoder.spi.operate.multiplication;
      
      import cn.bigcoder.spi.operate.service.INumOperate;
      
      /**
       * @author: Jindong.Tian
       * @date: 2020-11-29
       * @description:
       **/
      public class NumMultiOperateImpl implements INumOperate {
          
          public int exec(int num1, int num2) {
              return num1 * num2;
          }
      }
      

      同樣的在resource/METAINF/resoures目錄下創建cn.bigcoder.spi.operate.service.INumOperate文件:

      cn.bigcoder.spi.operate.multiplication.NumMultiOperateImpl
      

      3.4 spi-operate-consumer模塊

      spi-operate-consumer模塊中,我們編寫測試類獲取classpath中INumOperate實現類:

      package cn.bigcoder.spi.operate;
      
      import cn.bigcoder.spi.operate.service.INumOperate;
      import org.junit.Test;
      
      import java.util.Iterator;
      import java.util.ServiceLoader;
      
      /**
       * @author: Jindong.Tian
       * @date: 2020-11-29
       * @description:
       **/
      public class INumOperateTest {
          @Test
          public void test() {
              // SPI機制,尋找所有的實現類,順序執行
              ServiceLoader<INumOperate> loader = ServiceLoader.load(INumOperate.class);
              Iterator<INumOperate> iterator = loader.iterator();
              if (iterator.hasNext()) {
                  INumOperate numOperate = iterator.next();
                  System.out.println(numOperate.exec(1, 2));
              } else {
                  throw new RuntimeException("classpath中未找到cn.bigcoder.spi.operate.INumOperate實現類");
              }
          }
      }
      

      此時如果我們在spi-operate-consumer中引入spi-operate-add,則測試方法執行求和操作;如果引入spi-operate-multiplication,則測試方法執行乘法操作。

      本文涉及的源碼:java-spi-demo

      四. 聲明

      本文參考至:

      JAVA SPI機制詳解 - 簡書 (jianshu.com)

      Java SPI 的原理與應用 | crossoverJie’s Blog

      posted @ 2021-05-14 17:18  聽到微笑  閱讀(41)  評論(0)    收藏  舉報  來源
      主站蜘蛛池模板: 亚洲综合国产成人丁香五| 日韩精品中文字幕国产一| 久久亚洲精品国产精品尤物| 加勒比在线中文字幕一区二区| 大埔县| 国产熟女高潮一区二区三区| 成人免费A级毛片无码片2022| 实拍女处破www免费看| 亚洲熟妇自偷自拍另欧美| 亚洲色在线v中文字幕| 黄色段片一区二区三区| 国产亚洲精品AA片在线播放天| 亚洲乱熟乱熟女一区二区| 国产精品亚洲二区在线播放| 亚洲熟妇无码八av在线播放| 亚洲午夜无码久久久久小说| 一区二区三区久久精品国产| 狠狠色丁香婷婷亚洲综合| 日本精品不卡一二三区| 国产极品美女高潮抽搐免费网站 | 国产免费高清69式视频在线观看| 午夜亚洲www湿好爽| 免费无码影视在线观看mov| 国产成人午夜福利在线播放| 久久久久国色av免费观看性色| 日韩乱码人妻无码中文字幕视频| 国产精品黄色一区二区三区| 最新成免费人久久精品| 国产不卡免费一区二区| 成在线人免费视频| 亚洲精品国产aⅴ成拍色拍| 国产不卡一区不卡二区| 国产欧亚州美日韩综合区| 亚洲精品欧美综合二区| 亚洲av成人在线一区| 国产亚洲另类无码专区| 欧美大片va欧美在线播放| 亚洲精品无码久久一线| 国产成人精品国内自产色| 久久久这里只有精品10| 大尺度国产一区二区视频|