偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

開(kāi)發(fā) 后端
繼 2014 年 3 月 Java 8 發(fā)布之后,時(shí)隔 4 年,2018 年 9 月,Java 11 如期發(fā)布,其間間隔了 Java 9 和 Java 10 兩個(gè)非LTS(Long Term Support)版本。

 繼 2014 年 3 月 Java 8 發(fā)布之后,時(shí)隔 4 年,2018 年 9 月,Java 11 如期發(fā)布,其間間隔了 Java 9 和 Java 10 兩個(gè)非LTS(Long Term Support)版本。作為最新的LTS版本,相比 Java 8,Java 11 包含了模塊系統(tǒng)、改用 G1 作為默認(rèn) GC 算法、反應(yīng)式流 Flow、新版 HttpClient 等諸多特性。作為 JDK 11 升級(jí)系列的第一篇,本文將介紹此次升級(jí)最重要的特性——模塊系統(tǒng)。

[[332350]]

1、模塊系統(tǒng)簡(jiǎn)介

如果把 Java 8 比作單體應(yīng)用,那么引入模塊系統(tǒng)之后,從 Java 9 開(kāi)始,Java 就華麗的轉(zhuǎn)身為微服務(wù)。模塊系統(tǒng),項(xiàng)目代號(hào) Jigsaw,最早于 2008 年 8 月提出(比 Martin Fowler 提出微服務(wù)還早 6 年),2014 年跟隨 Java 9 正式進(jìn)入開(kāi)發(fā)階段,最終跟隨 Java 9 發(fā)布于 2017 年 9 月。

那么什么是模塊系統(tǒng)?官方的定義是A uniquely named, reusable group of related packages, as well as resources (such as images and XML files) and a module descriptor.如圖-1所示,模塊的載體是 jar 文件,一個(gè)模塊就是一個(gè) jar 文件,但相比于傳統(tǒng)的 jar 文件,模塊的根目錄下多了一個(gè)module-info.class 文件,也即 module descriptor。 module descriptor 包含以下信息:

  • 模塊名稱(chēng)
  • 依賴(lài)哪些模塊
  • 導(dǎo)出模塊內(nèi)的哪些包(允許直接 import 使用)
  • 開(kāi)放模塊內(nèi)的哪些包(允許通過(guò) Java 反射訪問(wèn))
  • 提供哪些服務(wù)
  • 依賴(lài)哪些服務(wù)

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

 

圖-1: Java 9 Module

也就是說(shuō),任意一個(gè) jar 文件,只要加上一個(gè)合法的 module descriptor,就可以升級(jí)為一個(gè)模塊。這個(gè)看似微小的改變,到底可以帶來(lái)哪些好處?在我看來(lái),至少帶來(lái)四方面的好處。

第一,原生的依賴(lài)管理。有了模塊系統(tǒng),Java 可以根據(jù) module descriptor計(jì)算出各個(gè)模塊間的依賴(lài)關(guān)系,一旦發(fā)現(xiàn)循環(huán)依賴(lài),啟動(dòng)就會(huì)終止。同時(shí),由于模塊系統(tǒng)不允許不同模塊導(dǎo)出相同的包(即 split package,分裂包),所以在查找包時(shí),Java 可以精準(zhǔn)的定位到一個(gè)模塊,從而獲得更好的性能。

第二,精簡(jiǎn) JRE。引入模塊系統(tǒng)之后,JDK 自身被劃分為 94 個(gè)模塊(參見(jiàn)圖-2)。通過(guò) Java 9 新增的 jlink 工具,開(kāi)發(fā)者可以根據(jù)實(shí)際應(yīng)用場(chǎng)景隨意組合這些模塊,去除不需要的模塊,生成自定義 JRE,從而有效縮小 JRE 大小。得益于此,JRE 11 的大小僅為 JRE 8 的 53%,從 218.4 MB縮減為 116.3 MB,JRE 中廣為詬病的巨型 jar 文件 rt.jar 也被移除。更小的 JRE 意味著更少的內(nèi)存占用,這讓 Java 對(duì)嵌入式應(yīng)用開(kāi)發(fā)變得更友好。

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

 

圖-2: The Modular JDK

第三,更好的兼容性。自打 Java 出生以來(lái),就只有 4 種包可見(jiàn)性,這讓 Java 對(duì)面向?qū)ο蟮娜筇卣髦环庋b的支持大打折扣,類(lèi)庫(kù)維護(hù)者對(duì)此叫苦不迭,只能一遍又一遍的通過(guò)各種文檔或者奇怪的命名來(lái)強(qiáng)調(diào)這些或者那些類(lèi)僅供內(nèi)部使用,擅自使用后果自負(fù)云云。Java 9 之后,利用 module descriptor 中的 exports 關(guān)鍵詞,模塊維護(hù)者就精準(zhǔn)控制哪些類(lèi)可以對(duì)外開(kāi)放使用,哪些類(lèi)只能內(nèi)部使用,換句話說(shuō)就是不再依賴(lài)文檔,而是由編譯器來(lái)保證。類(lèi)可見(jiàn)性的細(xì)化,除了帶來(lái)更好的兼容性,也帶來(lái)了更好的安全性。

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

 

圖-3: Java Accessibility

第四,提升 Java 語(yǔ)言開(kāi)發(fā)效率。Java 9 之后,Java 像開(kāi)掛了一般,一改原先一延再延的風(fēng)格,嚴(yán)格遵循每半年一個(gè)大版本的發(fā)布策略,從 2017 年 9 月到 2020 年 3 月,從 Java 9 到 Java 14,三年時(shí)間相繼發(fā)布了 6 個(gè)版本,無(wú)一延期,參見(jiàn)圖-4。這無(wú)疑跟模塊系統(tǒng)的引入有莫大關(guān)系。前文提到,Java 9 之后,JDK 被拆分為 94 個(gè)模塊,每個(gè)模塊有清晰的邊界(module descriptor)和獨(dú)立的單元測(cè)試,對(duì)于每個(gè) Java 語(yǔ)言的開(kāi)發(fā)者而言,每個(gè)人只需要關(guān)注其所負(fù)責(zé)的模塊,開(kāi)發(fā)效率因此大幅提升。這其中的差別,就好比單體應(yīng)用架構(gòu)升級(jí)到微服務(wù)架構(gòu)一般,版本迭代速度不快也難。

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

 

圖-4: Java SE Lifecycle

2、基礎(chǔ)篇

2.1 module descriptor

上面提到,模塊的核心在于 module descriptor,對(duì)應(yīng)根目錄下的 module-info.class 文件,而這個(gè) class 文件是由源代碼根目錄下的 module-info.java 編譯生成。Java 為 module-info.java 設(shè)計(jì)了專(zhuān)用的語(yǔ)法,包含 module、 requires、exports等多個(gè)關(guān)鍵詞(參見(jiàn)圖-5)。

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

 

圖-5: module-info.java 語(yǔ)法

語(yǔ)法解讀:

  • [open] module : 聲明一個(gè)模塊,模塊名稱(chēng)應(yīng)全局唯一,不可重復(fù)。加上 open 關(guān)鍵詞表示模塊內(nèi)的所有包都允許通過(guò) Java 反射訪問(wèn),模塊聲明體內(nèi)不再允許使用 opens 語(yǔ)句。
  • requires [transitive] : 聲明模塊依賴(lài),一次只能聲明一個(gè)依賴(lài),如果依賴(lài)多個(gè)模塊,需要多次聲明。加上 transitive 關(guān)鍵詞表示傳遞依賴(lài),比如模塊 A 依賴(lài)模塊 B,模塊 B 傳遞依賴(lài)模塊 C,那么模塊 A 就會(huì)自動(dòng)依賴(lài)模塊 C,類(lèi)似于 Maven。
  • exports [to [, ...]]: 導(dǎo)出模塊內(nèi)的包(允許直接 import 使用),一次導(dǎo)出一個(gè)包,如果需要導(dǎo)出多個(gè)包,需要多次聲明。如果需要定向?qū)С?,可以使?to 關(guān)鍵詞,后面加上模塊列表(逗號(hào)分隔)。
  • opens [to [, ...]]: 開(kāi)放模塊內(nèi)的包(允許通過(guò) Java 反射訪問(wèn)),一次開(kāi)放一個(gè)包,如果需要開(kāi)放多個(gè)包,需要多次聲明。如果需要定向開(kāi)放,可以使用 to 關(guān)鍵詞,后面加上模塊列表(逗號(hào)分隔)。
  • provides with [, ...]: 聲明模塊提供的 Java SPI 服務(wù),一次可以聲明多個(gè)服務(wù)實(shí)現(xiàn)類(lèi)(逗號(hào)分隔)。
  • uses : 聲明模塊依賴(lài)的 Java SPI 服務(wù),加上之后模塊內(nèi)的代碼就可以通過(guò) ServiceLoader.load(Class) 一次性加載所聲明的 SPI 服務(wù)的所有實(shí)現(xiàn)類(lèi)。

2.2 -p & -m 參數(shù)

Java 9 引入了一系列新的參數(shù)用于編譯和運(yùn)行模塊,其中最重要的兩個(gè)參數(shù)是 -p 和 -m。-p 參數(shù)指定模塊路徑,多個(gè)模塊之間用 “:”(Mac, Linux)或者 “;”(Windows)分隔,同時(shí)適用于 javac 命令和 java 命令,用法和Java 8 中的 -cp非常類(lèi)似。-m 參數(shù)指定待運(yùn)行的模塊主函數(shù),輸入格式為模塊名/主函數(shù)所在的類(lèi)名,僅適用于 java 命令。兩個(gè)參數(shù)的基本用法如下:

  • javac -p <module_path> <source>
  • java -p <module_path> -m <module>/<main_class>

2.3 Demo 示例

為了幫助你理解 module descriptor 語(yǔ)法和新的 Java 參數(shù),我專(zhuān)門(mén)設(shè)計(jì)了一個(gè)示例工程,其內(nèi)包含了 5 個(gè)模塊:

  • mod1 模塊: 主模塊,展示了使用服務(wù)實(shí)現(xiàn)類(lèi)的兩種方式。
  • mod2a 模塊: 分別導(dǎo)出和開(kāi)放了一個(gè)包,并聲明了兩個(gè)服務(wù)實(shí)現(xiàn)類(lèi)。
  • mod2b 模塊: 聲明了一個(gè)未公開(kāi)的服務(wù)實(shí)現(xiàn)類(lèi)。
  • mod3 模塊: 定義 SPI 服務(wù)(IEventListener),并聲明了一個(gè)未公開(kāi)的服務(wù)實(shí)現(xiàn)類(lèi)。
  • mod4 模塊: 導(dǎo)出公共模型類(lèi)。

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

圖-6: 包含 5 個(gè)模塊的示例工程

先來(lái)看一下主函數(shù),方式 1 展示了直接使用 mod2 導(dǎo)出和開(kāi)放的兩個(gè) IEventListener 實(shí)現(xiàn)類(lèi),方式 2 展示了通過(guò) Java SPI 機(jī)制使用所有的 IEventListener 實(shí)現(xiàn)類(lèi),無(wú)視其導(dǎo)出/開(kāi)放與否。方式 2 相比 方式 1,多了兩行輸出,分別來(lái)自于 mod2b 和 mod3 通過(guò) provides 關(guān)鍵詞提供的服務(wù)實(shí)現(xiàn)類(lèi)。

  1. public class EventCenter { 
  2.  
  3.     public static void main(String[] args) throws ReflectiveOperationException { 
  4.         // 方式1:通過(guò)exports和opens 
  5.         System.out.println("Demo: Direct Mode"); 
  6.         var listeners = new ArrayList<IEventListener>(); 
  7.         // 使用導(dǎo)出類(lèi) 
  8.         listeners.add(new EchoListener()); 
  9.         // 使用開(kāi)放類(lèi) 
  10.         // compile error: listeners.add(new ReflectEchoListener()); 
  11.         listeners.add((IEventListener<String>) Class.forName("mod2a.opens.ReflectEchoListener").getDeclaredConstructor().newInstance()); 
  12.         var event = Events.newEvent(); 
  13.         listeners.forEach(l -> l.onEvent(event)); 
  14.         System.out.println(); 
  15.  
  16.         // 方式2:通過(guò)SPI 
  17.         System.out.println("Demo: SPI Mode"); 
  18.         // 加載所有的IEventListener實(shí)現(xiàn)類(lèi),無(wú)視其導(dǎo)出/開(kāi)放與否 
  19.         var listeners2 = ServiceLoader.load(IEventListener.class).stream().map(ServiceLoader.Provider::get).collect(Collectors.toList()); 
  20.         // compile error: listeners.add(new InternalEchoListener()); 
  21.         // compile error: listeners.add(new SpiEchoListener()); 
  22.         var event2 = Events.newEvent(); 
  23.         listeners2.forEach(l -> l.onEvent(event2)); 
  24.     } 

代碼-1: mod1.EventCenter.java

命令行下執(zhí)行./build_mods.sh,得到輸出如下,結(jié)果和預(yù)期一致。

  1. Demo: Direct Mode 
  2. [echo] Event received: 68eb4671-c057-4bc2-9653-c31f5e3f72d2 
  3. [reflect echo] Event received: 68eb4671-c057-4bc2-9653-c31f5e3f72d2 
  4.  
  5. Demo: SPI Mode 
  6. [spi echo] Event received: 678d239a-77ef-4b7f-b7aa-e76041fcdf47 
  7. [echo] Event received: 678d239a-77ef-4b7f-b7aa-e76041fcdf47 
  8. [reflect echo] Event received: 678d239a-77ef-4b7f-b7aa-e76041fcdf47 
  9. [internal echo] Event received: 678d239a-77ef-4b7f-b7aa-e76041fcdf47 

代碼-2: EventCenter 結(jié)果輸出

3、進(jìn)階篇

看到這里,相信創(chuàng)建和運(yùn)行一個(gè)新的模塊應(yīng)用對(duì)你而言已經(jīng)不是問(wèn)題了,可問(wèn)題是老的 Java 8 應(yīng)用怎么辦?別著急,我們先來(lái)了解兩個(gè)高級(jí)概念,未命名模塊(unnamed module)和自動(dòng)模塊(automatic module)。

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

圖-7: 未命名模塊 vs 自動(dòng)模塊

一個(gè)未經(jīng)模塊化改造的 jar 文件是轉(zhuǎn)為未命名模塊還是自動(dòng)模塊,取決于這個(gè) jar 文件出現(xiàn)的路徑,如果是類(lèi)路徑,那么就會(huì)轉(zhuǎn)為未命名模塊,如果是模塊路徑,那么就會(huì)轉(zhuǎn)為自動(dòng)模塊。注意,自動(dòng)模塊也屬于命名模塊的范疇,其名稱(chēng)是模塊系統(tǒng)基于 jar 文件名自動(dòng)推導(dǎo)得出的,比如 com.foo.bar-1.0.0.jar 文件推導(dǎo)得出的自動(dòng)模塊名是 com.foo.bar。圖-7列舉了未命名模塊和自動(dòng)模塊行為上的區(qū)別,除此之外,兩者還有一個(gè)關(guān)鍵區(qū)別,分裂包規(guī)則適用于自動(dòng)模塊,但對(duì)未命名模塊無(wú)效,也即多個(gè)未命名模塊可以導(dǎo)出同一個(gè)包,但自動(dòng)模塊不允許。

未命名模塊和自動(dòng)模塊存在的意義在于,無(wú)論傳入的 jar 文件是否一個(gè)合法的模塊(包含 module descriptor),Java 內(nèi)部都可以統(tǒng)一的以模塊的方式進(jìn)行處理,這也是 Java 9 兼容老版本應(yīng)用的架構(gòu)原理。運(yùn)行老版本應(yīng)用時(shí),所有 jar 文件都出現(xiàn)在類(lèi)路徑下,也就是轉(zhuǎn)為未命名模塊,對(duì)于未命名模塊而言,默認(rèn)導(dǎo)出所有包并且依賴(lài)所有模塊,因此應(yīng)用可以正常運(yùn)行。進(jìn)一步的解讀可以參閱官方白皮書(shū)的相關(guān)章節(jié)。

基于未命名模塊和自動(dòng)模塊,相應(yīng)的就產(chǎn)生了兩種老版本應(yīng)用的遷移策略,或者說(shuō)模塊化策略。

3.1 Bottom-up 自底向上策略

第一種策略,叫做自底向上(bottom-up)策略,即根據(jù) jar 包依賴(lài)關(guān)系(如果依賴(lài)關(guān)系比較復(fù)雜,可以使用 jdeps 工具進(jìn)行分析),沿著依賴(lài)樹(shù)自底向上對(duì) jar 包進(jìn)行模塊化改造(在 jar 包的源代碼根目錄下添加合法的模塊描述文件 module-info.java)。初始時(shí),所有 jar 包都是非模塊化的,全部置于類(lèi)路徑下(轉(zhuǎn)為未命名模塊),應(yīng)用以傳統(tǒng)方式啟動(dòng)。然后,開(kāi)始自底向上對(duì) jar 包進(jìn)行模塊化改造,改造完的 jar 包就移到模塊路徑下,這期間應(yīng)用仍以傳統(tǒng)方式啟動(dòng)。最后,等所有 jar 包都完成模塊化改造,應(yīng)用改為 -m 方式啟動(dòng),這也標(biāo)志著應(yīng)用已經(jīng)遷移為真正的 Java 9 應(yīng)用。以上面的示例工程為例,

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

 

圖-8: Bottom-up模塊化策略

1.假設(shè)初始時(shí),所有 jar 包都是非模塊化的,此時(shí)應(yīng)用運(yùn)行命令為:

  1. java -cp mod1.jar:mod2a.jar:mod2b.jar:mod3.jar:mod4.jar mod1.EventCenter 

對(duì) mod3 和 mod4 進(jìn)行模塊化改造。完成之后,此時(shí) mod1, mod2a, mod2b 還是普通的 jar 文件,新的運(yùn)行命令為:

  1. java -cp mod1.jar:mod2a.jar:mod2b.jar -p mod3.jar:mod4.jar --add-modules mod3,mod4 mod1.EventCenter 

對(duì)比上一步的命令,首先 mod3.jar 和 mod4.jar 從類(lèi)路徑移到了模塊路徑,這個(gè)很好理解,因?yàn)檫@兩個(gè) jar 包已經(jīng)改造成了真正的模塊。其次,多了一個(gè)額外的參數(shù) --add-modules mod3,mod4,這是為什么呢?這就要談到模塊系統(tǒng)的模塊發(fā)現(xiàn)機(jī)制了。

不管是編譯時(shí),還是運(yùn)行時(shí),模塊系統(tǒng)首先都要確定一個(gè)或者多個(gè)根模塊(root module),然后從這些根模塊開(kāi)始根據(jù)模塊依賴(lài)關(guān)系在模塊路徑中循環(huán)找出所有可觀察到的模塊(observable module),這些可觀察到的模塊加上類(lèi)路徑下的 jar 文件最終構(gòu)成了編譯時(shí)環(huán)境和運(yùn)行時(shí)環(huán)境。那么根模塊是如何確定的呢?對(duì)于運(yùn)行時(shí)而言,如果應(yīng)用是通過(guò) -m 方式啟動(dòng)的,那么根模塊就是 -m 指定的主模塊;如果應(yīng)用是通過(guò)傳統(tǒng)方式啟動(dòng)的,那么根模塊就是所有的 java.* 模塊即 JRE(參見(jiàn)圖-2)?;氐角懊娴睦?,如果不加 --add-modules 參數(shù),那么運(yùn)行時(shí)環(huán)境中除了 JRE 就只有 mod1.jar、mod2a.jar、mod2b.jar,沒(méi)有 mod3、mod4 模塊,就會(huì)報(bào) java.lang.ClassNotFoundException 異常。如你所想,--add-modules 參數(shù)的作用就是手動(dòng)指定額外的根模塊,這樣應(yīng)用就可以正常運(yùn)行了。

3.接著完成 mod2a、mod2b 的模塊化改造,此時(shí)運(yùn)行命令為:

java -cp mod1.jar -p mod2a.jar:mod2b.jar:mod3.jar:mod4.jar --add-modules mod2a,mod2b,mod4 mod1.EventCenter

由于 mod2a、mod2b 都依賴(lài) mod3,所以 mod3 就不用加到 --add-modules 參數(shù)里了。

4.最后完成 mod1 的模塊化改造,最終運(yùn)行命令就簡(jiǎn)化為:

java -p mod1.jar:mod2a.jar:mod2b.jar:mod3.jar:mod4.jar -m mod1/mod1.EventCenter

注意此時(shí)應(yīng)用是以 -m 方式啟動(dòng),并且指定了 mod1 為主模塊(也是根模塊),因此所有其他模塊根據(jù)依賴(lài)關(guān)系都會(huì)被識(shí)別為可觀察到的模塊并加入到運(yùn)行時(shí)環(huán)境,應(yīng)用可以正常運(yùn)行。

3.2 Top-down 自上而下策略

自底向上策略很容易理解,實(shí)施路徑也很清晰,但它有一個(gè)隱含的假設(shè),即所有 jar 包都是可以模塊化的,那如果其中有 jar 包無(wú)法進(jìn)行模塊化改造(比如 jar 包是一個(gè)第三方類(lèi)庫(kù)),怎么辦?別慌,我們?cè)賮?lái)看第二種策略,叫做自上而下(top-down)策略。

它的基本思路是,根據(jù) jar 包依賴(lài)關(guān)系,從主應(yīng)用開(kāi)始,沿著依賴(lài)樹(shù)自上而下分析各個(gè) jar 包模塊化改造的可能性,將 jar 包分為兩類(lèi),一類(lèi)是可以改造的,一類(lèi)是無(wú)法改造的。對(duì)于第一類(lèi),我們?nèi)匀徊捎米缘紫蛏喜呗赃M(jìn)行改造,直至主應(yīng)用完成改造,對(duì)于第二類(lèi),需要從一開(kāi)始就放入模塊路徑,即轉(zhuǎn)為自動(dòng)模塊。這里就要談一下自動(dòng)模塊設(shè)計(jì)的精妙之處,首先,自動(dòng)模塊會(huì)導(dǎo)出所有包,這樣就保證第一類(lèi) jar 包可以照常訪問(wèn)自動(dòng)模塊,其次,自動(dòng)模塊依賴(lài)所有命名模塊,并且允許訪問(wèn)所有未命名模塊的類(lèi)(這一點(diǎn)很重要,因?yàn)槌詣?dòng)模塊之外,其它命名模塊是不允許訪問(wèn)未命名模塊的類(lèi)),這樣就保證自動(dòng)模塊自身可以照常訪問(wèn)其他類(lèi)。等到主應(yīng)用完成模塊化改造,應(yīng)用的啟動(dòng)方式就可以改為 -m方式。

還是以示例工程為例,假設(shè) mod4 是一個(gè)第三方 jar 包,無(wú)法進(jìn)行模塊化改造,那么最終改造完之后,雖然應(yīng)用運(yùn)行命令和之前一樣還是java -p mod1.jar:mod2a.jar:mod2b.jar:mod3.jar:mod4.jar -m mod1/mod1.EventCenter,但其中只有 mod1、mod2a、mod2b、mod3 是真正的模塊,mod4 未做任何改造,借由模塊系統(tǒng)轉(zhuǎn)為自動(dòng)模塊。

 

「JDK 11」關(guān)于 Java 模塊系統(tǒng),看這一篇就夠了

 

圖-9: Top-down模塊化策略

看上去很完美,不過(guò)等一下,如果有多個(gè)自動(dòng)模塊,并且它們之間存在分裂包呢?前面提到,自動(dòng)模塊和其它命名模塊一樣,需要遵循分裂包規(guī)則。對(duì)于這種情況,如果模塊化改造勢(shì)在必行,要么忍痛割?lèi)?ài)精簡(jiǎn)依賴(lài)只保留其中的一個(gè)自動(dòng)模塊,要么自己動(dòng)手豐衣足食 Hack 一個(gè)版本。當(dāng)然,你也可以試試找到這些自動(dòng)模塊的維護(hù)者們,讓他們 PK 一下決定誰(shuí)才是這個(gè)分裂包的主人。

4、番外篇

有關(guān)模塊系統(tǒng)的介紹到這就基本結(jié)束了,簡(jiǎn)單回顧一下,首先我介紹了什么是模塊、模塊化的好處,接著給出了定義模塊的語(yǔ)法,和編譯、運(yùn)行模塊的命令,并輔以一個(gè)示例工程進(jìn)行說(shuō)明,最后詳細(xì)闡述了老版本應(yīng)用模塊化改造的思路?,F(xiàn)在我們?cè)賮?lái)看一些跟模塊系統(tǒng)比較相似的框架和工具,以進(jìn)一步加深你對(duì)模塊系統(tǒng)的理解。

4.1 vs OSGi

說(shuō)起模塊化,尤其在 Java 界,那么肯定繞不過(guò) OSGi 這個(gè)模塊系統(tǒng)的鼻祖。OSGi 里的 bundle 跟模塊系統(tǒng)里的模塊非常相似,都是以 jar 文件的形式存在,每個(gè) bundle 有自己的名稱(chēng),也會(huì)定義依賴(lài)的 bundle、導(dǎo)出的包、發(fā)布的服務(wù)等。所不同的是,OSGi bundle 可以定義版本,還有生命周期的概念,包括 installed、resolved、uninstalled、starting、active、stopping 6 種狀態(tài),所有 bundle 都由 OSGi 容器進(jìn)行管理,并且在同一個(gè) OSGi 容器里面允許同時(shí)運(yùn)行同一個(gè) bundle 的多個(gè)版本,甚至每個(gè) bundle 有各自獨(dú)立的 classloader。以上種種特性使得 OSGi 框架變得非常重,在微服務(wù)盛行的當(dāng)下,越來(lái)越被邊緣化。

4.2 vs Maven

Maven 的依賴(lài)管理和模塊系統(tǒng)存在一些相似之處,Maven 里的 artifact 對(duì)應(yīng)模塊 ,都是以 jar 文件的形式存在,有名稱(chēng),可以聲明傳遞依賴(lài)。不同之處在于,Maven artifact 支持版本,但缺少包一級(jí)的信息,也沒(méi)有服務(wù)的概念。如果 Java 一出生就帶有模塊系統(tǒng),那么 Maven 的依賴(lài)管理大概率就會(huì)直接基于模塊系統(tǒng)來(lái)設(shè)計(jì)了。

4.3 vs ArchUnit

ArchUnit 在包可見(jiàn)性方面的控制能力和模塊系統(tǒng)相比,有過(guò)之而無(wú)不及,并且可以細(xì)化到類(lèi)、方法、屬性這一級(jí)。但 ArchUnit 缺少模塊一級(jí)的控制,模塊系統(tǒng)的出現(xiàn)正好補(bǔ)齊了 ArchUnit 這一方面的短板,兩者相輔相成、相得益彰,以后落地架構(gòu)規(guī)范也省了很多口水。

 

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2025-08-07 04:10:00

光模塊AI網(wǎng)絡(luò)

2017-03-11 22:19:09

深度學(xué)習(xí)

2020-07-03 08:21:57

Java集合框架

2023-02-10 09:04:27

2020-02-18 16:20:03

Redis ANSI C語(yǔ)言日志型

2022-06-20 09:01:23

Git插件項(xiàng)目

2022-04-07 10:39:21

反射Java安全

2022-08-01 11:33:09

用戶(hù)分析標(biāo)簽策略

2021-04-08 07:37:39

隊(duì)列數(shù)據(jù)結(jié)構(gòu)算法

2023-09-11 08:13:03

分布式跟蹤工具

2019-05-14 09:31:16

架構(gòu)整潔軟件編程范式

2018-05-22 08:24:50

PythonPyMongoMongoDB

2024-09-23 08:00:00

消息隊(duì)列MQ分布式系統(tǒng)

2023-10-17 08:15:28

API前后端分離

2023-11-18 09:30:42

模型AI

2020-11-22 08:32:29

人工智能AI

2022-05-19 08:28:19

索引數(shù)據(jù)庫(kù)

2022-07-06 12:07:06

Python函數(shù)式編程

2020-10-18 07:32:06

SD-WAN網(wǎng)絡(luò)傳統(tǒng)廣域網(wǎng)

2020-10-21 14:12:02

Single Sign
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)