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

Java和Dubbo的SPI機制原理解析

 更新時間:2021年03月22日 09:23:49   作者:luzaichun  
這篇文章主要介紹了Java和Dubbo的SPI機制原理解析,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

SPI: 簡單理解就是,你一個接口有多種實現(xiàn),然后在代碼運行時候,具體選用那個實現(xiàn),這時候我們就可以通過一些特定的方式來告訴程序?qū)び媚莻€實現(xiàn)類,這就是SPI。

JAVA的SPI

全稱為 Service Provider Interface,是一種服務(wù)發(fā)現(xiàn)機制。它是約定在 Classpath 下的 META-INF/services/ 目錄里創(chuàng)建一個以服務(wù)接口命名的文件,然后文件里面記錄的是此 jar 包提供的具體實現(xiàn)類的全限定名。

這樣當我們引用了某個 jar 包的時候就可以去找這個 jar 包的 META-INF/services/ 目錄,再根據(jù)接口名找到文件,然后讀取文件里面的內(nèi)容去進行實現(xiàn)類的加載與實例化。

例如:

java的jdbc就使用了SPI機制,當我項目種應(yīng)用了mysql的連接jar時候,就會去去mysql-connector-java.jar下的META-INF/services/ 目錄查找java.sql.Driver名的文件,然后加載里面全類名的類。如果使用oracle連接驅(qū)動時候,就會去ojdbc.jar下面去找java.sql.Driver文件里的配置的全類名。

在這里插入圖片描述

在這里插入圖片描述

并且通過IDEA的智能提示功能,也能看到,在你切換不同連接的jar包時候,Driver接口實現(xiàn)類是不同的。

使用mysql的連接驅(qū)動:

在這里插入圖片描述

切換到oracle的連接驅(qū)動:

在這里插入圖片描述

Java的SPI機制源碼分析

下面這段代碼,以jdbc的SPI為例,可以作為debug的入口:

package com.example.demo;

import java.sql.Connection;
import java.sql.DriverManager;
/**
 * @author:luzaichun
 * @Date:2021/3/14
 * @Time:14:09
 **/
public class JDBCMain {
  private static final String URL = "jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=UTF-8";

  public static void main(String[] args) throws Exception{
    Connection conn = DriverManager.getConnection(URL, "root", "123456");
  }
}

在使用DriverManager.getConnection()方法時候,會加載并初始化DriverManager類,此類是jdbc使用SPI的核心類。

1.DriverManager類初始化,調(diào)用static代碼塊,執(zhí)行DriverManager#loadInitialDrivers()方法

在這里插入圖片描述

2.使用javaSPI的核心類ServiceLoader#load()和以及其內(nèi)部實現(xiàn)了Iterator的LazyIterator#hasNext()和
LazyIterator#next(),加載接口的具體實現(xiàn)類。

在這里插入圖片描述

ServiceLoader.load()整個代碼流程,如下圖。其實就是給LazyIterator類的賦值屬性,是那個接口要進行SPI,使用的類加載器是哪一個。

在這里插入圖片描述 

driversIterator.hasNext()和driversIterator.next()方法負責類實際類的加載

  •  driversIterator.hasNext()最后實際是調(diào)到了LazyIterator.hasNext();
  • driversIterator.next()最后實際是調(diào)到了LazyIterator.next();

hashNext()方法讀到SPI的配置文件里的全類名

在這里插入圖片描述

next()方法最后通過反射創(chuàng)建出具體實現(xiàn)類的實例

在這里插入圖片描述

總結(jié):

  1. jdbc的SPI,通過DriverManager類靜態(tài)代碼塊執(zhí)行l(wèi)oadInitialDrivers()方法
  2. 然后通過ServiceLoader.load()拿到具體的接口,以及類加載器。
  3. 通過實現(xiàn)了Iterator類的LazyIterator類的hasNext方法讀取配置文件,拿到接口的具體實現(xiàn)全類名
  4. 在next()方法內(nèi)部,通過反射機制,由實現(xiàn)類的全類名,加載具體實現(xiàn)類。

代碼實戰(zhàn)java SPI

DemoService接口

public interface DemoService {
  String sayHello(String msg);
} 

XiaoHongDemoServiceImpl實現(xiàn)類

public class XiaoHongDemoServiceImpl implements DemoService {
  @Override
  public String sayHello(String msg) {
    return "xiaohong:"+msg;
  }
}

ZhangSanDemoServiceImpl實現(xiàn)類

public class ZhangSanDemoServiceImpl implements DemoService {
  @Override
  public String sayHello(String msg) {
    return "zhangsan:"+msg;
  }
}

定義SPI配置文件

在這里插入圖片描述

最后使用

public class DemoMain {
  public static void main(String[] args) {
    ServiceLoader<DemoService> serviceLoad = ServiceLoader.load(DemoService.class);
    Iterator<DemoService> iterator = serviceLoad.iterator();
    while (iterator.hasNext()){
      DemoService demoService = iterator.next();
      String returnStr = demoService.sayHello("lzc賊帥?。。?!");
      System.out.println(returnStr);
    }
  }
}

執(zhí)行結(jié)果:

在這里插入圖片描述

java SPI劣勢,會加載SPI配置文件里定義的所有配置類,如果用不上該類,也會加載。通俗點講,就是無法按需加載。

Dubbo的SPI

dubbo SPI使用

需要先引入dubbo相關(guān)的依賴

1.定義接口
通過dubbo的SPI注解標注定義的接口

@SPI("xiaohong")
public interface DubboSPIService {

  void sayHello();
}

2.多個實現(xiàn)類

public class XiaoHongDubboSPIServiceImpl implements DubboSPIService {
  @Override
  public void sayHello() {
    System.out.println("小紅說:lzc賊帥!");
  }
}
public class XiaoMingDubboSPIServiceImpl implements DubboSPIService {
  @Override
  public void sayHello() {
    System.out.println("小明說:lzc賊帥!");
  }
}

3.定義dubbo SPI配置文件
META-INF/dubbo目錄下定義接口全類名的文件,配置key-value的實現(xiàn)

Dubbo 對配置文件目錄的約定,不同于 Java SPI ,Dubbo 分為了三類目錄。

META-INF/services/ 目錄:該目錄下的 SPI 配置文件是為了用來兼容 Java SPI 。
META-INF/dubbo/ 目錄:該目錄存放用戶自定義的 SPI 配置文件。
META-INF/dubbo/internal/ 目錄:該目錄存放 Dubbo 內(nèi)部使用的 SPI 配置文件。

在這里插入圖片描述

4.使用

public class DubboSPIMain {
  public static void main(String[] args) {
  //default,會取@SPI注解里定義的key對應(yīng)的實現(xiàn)
//    DubboSPIService defaultExtensionService = ExtensionLoader.getExtensionLoader(DubboSPIService.class).getDefaultExtension();
//    defaultExtensionService.sayHello();
    DubboSPIService dubboSPIService = ExtensionLoader.getExtensionLoader(DubboSPIService.class).getExtension("xiaoming");
    dubboSPIService.sayHello();
  }
}

結(jié)果:

在這里插入圖片描述

源碼分析

ExtensionLoader.getExtensionLoader(DubboSPIService.class).getExtension("xiaoming");
dubbo SPI的核心就是ExtensionLoader類

1.ExtensionLoader#getExtensionLoader()

該方法主要是,從一個map里取key為當前傳進來的接口Class的value(value是ExtensionLoader對象),如果取不到,我們就往這個map里put一份這樣的key-value。value是new ExtensionLoader(type)傳進去的type是接口的Class對象,最后會賦值給ExtensionLoader對象的type屬性,后面會用到

在這里插入圖片描述

2.拿到ExtensionLoader對象后,通過ExtensionLoader#getExtension()獲取具體的實現(xiàn)的實例

首先會取緩存里拿,沒拿到就調(diào)用createExtension()方法取創(chuàng)建所需要的實例,最后塞入緩存。

在這里插入圖片描述

3.createExtension方法

通過getExtension(“xiaoming”)傳進來的name=xiaoming,從SPI配置文件獲取到所需要實現(xiàn)類的全類名,通過反射拿到實現(xiàn)類的Class對象,最后通過反射拿到相應(yīng)的實例。核心是getExtensionClasses()方法。

在這里插入圖片描述

4.getExtensionClasses()

getExtensionClasses()方法返回一個Map,key為SPI配置文件中的key,value為SPI配置文件中,實現(xiàn)類的Class對象。

可以看到,代碼中用來大量的緩存機制,鎖的雙檢查。cacheDefaultExtensionName()方法里會拿到SPI注解上配置的默認key,然后賦值給cachedDefaultName屬性,如果使用getDefaultExtension()時候會使用到strategies,其實是通過java得SPI拿到得一個數(shù)組

在這里插入圖片描述

5.循環(huán)三個SPI文件得目錄,分別調(diào)用loadDirectory方法

fileName最后在三次循環(huán)里,會拼出三個路徑,META-INF/dubbo/com.example.demo.service.DubboSPIService,這一個才是正確得路徑,然后獲得配置文件得絕對路徑。然后會執(zhí)行l(wèi)oadResource()方法讀取SPI配置文件

  • META-INF/dubbo/com.example.demo.service.DubboSPIService
  • META-INF/services/com.example.demo.service.DubboSPIService
  • META-INF/dubbo/internal/com.example.demo.service.DubboSPIService

在這里插入圖片描述
在這里插入圖片描述 

6.loadResource()讀取SPI配置文件

一行一行讀配置文件里得key-value,然后通過Class.forName()獲取類得Class對象。然后put到第四步定義得空Map,extensionClasses這個Map里,再返回到第三步得getExtensionClasses()方法。

在這里插入圖片描述

好了,今天先到這里,凌晨了。。。Adaptive 注解 - 自適應(yīng)擴展下次有時間再寫。

到此這篇關(guān)于Java和Dubbo的SPI機制原理解析的文章就介紹到這了,更多相關(guān)Java和Dubbo的SPI內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中MapStruct實現(xiàn)優(yōu)雅的數(shù)據(jù)復(fù)制

    SpringBoot中MapStruct實現(xiàn)優(yōu)雅的數(shù)據(jù)復(fù)制

    本文主要介紹了SpringBoot中MapStruct實現(xiàn)優(yōu)雅的數(shù)據(jù)復(fù)制,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • 使用Flyway進行Java數(shù)據(jù)庫版本控制的操作指南

    使用Flyway進行Java數(shù)據(jù)庫版本控制的操作指南

    今天我們將深入探討如何使用Flyway進行Java數(shù)據(jù)庫版本控制,Flyway是一個流行的數(shù)據(jù)庫遷移工具,用于管理和自動化數(shù)據(jù)庫模式的演變,文中通過代碼示例介紹的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-07-07
  • string類和LocalDateTime的相互轉(zhuǎn)換方式

    string類和LocalDateTime的相互轉(zhuǎn)換方式

    這篇文章主要介紹了string類和LocalDateTime的相互轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • java-synchronized 嵌套使用代碼詳解

    java-synchronized 嵌套使用代碼詳解

    本文以synchronized 的同步造成了死鎖為例,介紹了java-synchronized 嵌套使用代碼詳解,同時對鎖和死鎖的概念進行了說明,需要的朋友可以了解下。
    2017-09-09
  • SpringBoot整合Dubbo+Zookeeper實現(xiàn)RPC調(diào)用

    SpringBoot整合Dubbo+Zookeeper實現(xiàn)RPC調(diào)用

    這篇文章主要給大家介紹了Spring Boot整合Dubbo+Zookeeper實現(xiàn)RPC調(diào)用的步驟詳解,文中有詳細的代碼示例,對我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-07-07
  • JPA如何使用findBy方法自定義查詢

    JPA如何使用findBy方法自定義查詢

    這篇文章主要介紹了JPA如何使用findBy方法自定義查詢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringMVC的簡單傳值(實現(xiàn)代碼)

    SpringMVC的簡單傳值(實現(xiàn)代碼)

    下面小編就為大家?guī)硪黄猄pringMVC的簡單傳值(實現(xiàn)代碼)。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • Java排序之Comparable和Comparator比較器詳解

    Java排序之Comparable和Comparator比較器詳解

    這篇文章主要介紹了Java排序之Comparable和Comparator比較器詳解,Comparable<T>是內(nèi)部比較器,Comparator<T>是外部比較器,最推薦使用Comparator<T>接口排序,Comparator提供靜態(tài)方法很方便,推薦使用,需要的朋友可以參考下
    2024-01-01
  • 解決Maven打包只有幾十K,運行報錯no main manifest attribute問題

    解決Maven打包只有幾十K,運行報錯no main manifest attribute

    這篇文章主要介紹了解決Maven打包只有幾十K,運行報錯no main manifest attribute問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • springboot自帶的緩存@EnableCaching用法

    springboot自帶的緩存@EnableCaching用法

    這篇文章主要介紹了springboot自帶的緩存@EnableCaching用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評論

南木林县| 普兰县| 沙田区| 睢宁县| 三亚市| 永登县| 简阳市| 永昌县| 澄迈县| 安化县| 新绛县| 尚义县| 开平市| 柘荣县| 泸水县| 额尔古纳市| 南京市| 北川| 钦州市| 泸定县| 南川市| 隆化县| 三原县| 彭水| 江山市| 天祝| 涿鹿县| 十堰市| 天门市| 太谷县| 敦化市| 海兴县| 镇雄县| 陆川县| 明星| 天津市| 伊春市| 昌都县| 黔西县| 岑巩县| 遵化市|