JDK源码分析——Java的SPI机制分析与实战
重點提示:在我博客中的所有的源碼分析的實例,我都將會放到github上,感興趣的朋友可以下載下來調試運行,我相信還是可以有所收獲的。我的目的是讓所有讀到我博客的朋友都可以了解到有價值的東西,學習到java核心的原理,使用起來更加得心應手。
所有實例的GitHub地址:https://github.com/mh47838704/JavaExample ,我會不定期的更新代碼,所有大家可以長期關注一下。
前一段時間公司內部領導希望我們目前的產品的后臺開發使用微服務,讓我們調研分析一下,與此同時有朋友公司在使用dubbo,所以打算看看dubbo。
首先去dubbo的官網看一下官網的文檔,文檔描述的很詳細,對dubbo的整體的架構、運維部署、擴展機制等都做了詳細的介紹。并提出如何使用Java開發出穩定產品的一些心得體會,這些心得體會讓我深有同感,所以推薦大家也去看看,另外還強烈推薦把《Effective Java》反復研讀。
在了解了dubbo的框架和設計順便下載了dubbo的源碼看了之后呢,里面有一個spi機制在之前沒有接觸過,通過查看java的官方文檔了解到這種機制也是java提供的一種可擴展的一種編程機制,通過這種機制類似于插件機制,非常方便程序的擴展。
SPI機制分析
如果英文好而且又對Java理解的很深的,可以直接查看oracle的官網的介紹https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html ,在該篇文章中對什么是spi、spi的優點、如何開發自己的spi都進行詳細的介紹。本篇文章將按照官方的文檔,設計并測試相應的spi實例,并通過接口和spi對比測試來區分兩者之間的區別。
首先我們定義一個HelloService的接口,并編寫兩個實現類,類的關系如下圖所示?
HelloService.java
package com.mh.JavaExample.spi.imp;
/**
?* SPI機制分析實例
?* Start at: 2018/5/1 16:14
?*
?* @author muhong
?*/
public interface HelloService {
? ? void sayHello();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
ChinaHelloService.java
package com.mh.JavaExample.spi.imp;
/**
?* 中國式的招呼
?* Start at: 2018/5/1 16:17
?*
?* @author muhong
?*/
public class ChinaHelloService implements HelloService {
? ? @Override
? ? public void sayHello() {
? ? ? ? System.out.println("你好,世界!");
? ? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
AmericaHelloService.java
package com.mh.JavaExample.spi.imp;
/**
?* 美國式的招呼
?* Start at: 2018/5/1 16:18
?*
?* @author muhong
?*/
public class AmericaHelloService implements HelloService {
? ? @Override
? ? public void sayHello() {
? ? ? ? System.out.println("Hello world!");
? ? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
接口測試:?
在我們平常編程的時候,我們使用統一接口自定義實現的方式進行擴展,下面是基于接口的實現方式:
package com.mh.JavaExample.spi;
import com.mh.JavaExample.spi.imp.AmericaHelloService;
import com.mh.JavaExample.spi.imp.ChinaHelloService;
import com.mh.JavaExample.spi.imp.HelloService;
import org.junit.Test;
/**
?* 測試接口
?* Start at: 2018/5/1 16:22
?*
?* @author muhong
?*/
public class TestMain {
? ? @Test
? ? public void testInterface(){
? ? ? ? HelloService ch = new ChinaHelloService();
? ? ? ? ch.sayHello();
? ? ? ? HelloService en = new AmericaHelloService();
? ? ? ? en.sayHello();
? ? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
基于SPI的擴展的測試
package com.mh.JavaExample.spi;
import org.junit.Test;
import java.util.Iterator;
import java.util.ServiceLoader;
/**
?* 測試SPI
?* 關于SPI的jar包的打包方式,可以參考oracle的官網說明:https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html
?* 本次SPI的測試jar包也是參考該說明打包的:
?* 1、和spi相關的class文件拷貝到一個臨時目錄下/tmp(用戶自定創建,和打包無關)
?* 2、在該目錄下創建META-INF目錄,在META-INF目錄下創建services目錄,在目錄下創建com.mh.JavaExample.spi.HelloService文件
?* 3、在該文件中輸入SPI接口的名字,如com.mh.JavaExample.spi.AmericaHelloService
?* 4、進入到臨時根目錄/tmp中,執行命令jar cvf AmericaHelloService.jar -C . .
?* 5、在該根目錄下就可以看到AmericaHelloService.jar了
?* Start at: 2018/5/1 17:25
?*
?* @author muhong
?*/
public class TestMain2 {
? ? @Test
? ? public void testSpi(){
? ? ? ? ServiceLoader<HelloService> services = ServiceLoader.load(HelloService.class);
? ? ? ? for (Iterator<HelloService> iterator = services.iterator(); iterator.hasNext(); ) {
? ? ? ? ? ? HelloService helloService = iterator.next();
? ? ? ? ? ? helloService.sayHello();
? ? ? ? }
? ? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
源碼分析
相關的源碼我已經放到github上了,下面是和該實例相關的類和jar包,通過分析運行這些類和jar包可以對該機制有深入的了解,下面是代碼結構圖:?
在上面的圈中的文件中:
test目錄下的spi.imp中的代碼文件是用于接口測試的。
在lib中的三個jar包是用于spi測試的,其中HelloService.jar是屬于接口包,ChinaHelloService.jar和AmericaHelloService.jar是SPI的實現類,編寫打包的格式如下:?
總結?
通過閱讀oracle官方的介紹,可以完成自定義spi的開發,如果英文不是特別好的朋友,可以先查閱相關的博客資料,然后結合我的代碼去調試即可有深入的了解。
---------------------?
作者:m47838704?
來源:CSDN?
原文:https://blog.csdn.net/m47838704/article/details/80160985?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的JDK源码分析——Java的SPI机制分析与实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高级开发必须理解的Java中SPI机制
- 下一篇: 深入理解java SPI机制