自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

開發(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 開始,Java 就華麗的轉(zhuǎn)身為微服務(wù)。模塊系統(tǒng),項(xiàng)目代號(hào) Jigsaw,最早于 2008 年 8 月提出(比 Martin Fowler 提出微服務(wù)還早 6 年),2014 年跟隨 Java 9 正式進(jìn)入開發(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 包含以下信息:

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

 

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

 

圖-1: Java 9 Module

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

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

第二,精簡(jiǎn) JRE。引入模塊系統(tǒng)之后,JDK 自身被劃分為 94 個(gè)模塊(參見圖-2)。通過 Java 9 新增的 jlink 工具,開發(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)用開發(fā)變得更友好。

 

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

 

圖-2: The Modular JDK

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

 

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

 

圖-3: Java Accessibility

第四,提升 Java 語(yǔ)言開發(fā)效率。Java 9 之后,Java 像開掛了一般,一改原先一延再延的風(fēng)格,嚴(yán)格遵循每半年一個(gè)大版本的發(fā)布策略,從 2017 年 9 月到 2020 年 3 月,從 Java 9 到 Java 14,三年時(shí)間相繼發(fā)布了 6 個(gè)版本,無一延期,參見圖-4。這無疑跟模塊系統(tǒng)的引入有莫大關(guān)系。前文提到,Java 9 之后,JDK 被拆分為 94 個(gè)模塊,每個(gè)模塊有清晰的邊界(module descriptor)和獨(dú)立的單元測(cè)試,對(duì)于每個(gè) Java 語(yǔ)言的開發(fā)者而言,每個(gè)人只需要關(guān)注其所負(fù)責(zé)的模塊,開發(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ì)了專用的語(yǔ)法,包含 module、 requires、exports等多個(gè)關(guān)鍵詞(參見圖-5)。

 

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

 

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

語(yǔ)法解讀:

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

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非常類似。-m 參數(shù)指定待運(yùn)行的模塊主函數(shù),輸入格式為模塊名/主函數(shù)所在的類名,僅適用于 java 命令。兩個(gè)參數(shù)的基本用法如下:

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

2.3 Demo 示例

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

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

 

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

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

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

  1. public class EventCenter { 
  2.  
  3.     public static void main(String[] args) throws ReflectiveOperationException { 
  4.         // 方式1:通過exports和opens 
  5.         System.out.println("Demo: Direct Mode"); 
  6.         var listeners = new ArrayList<IEventListener>(); 
  7.         // 使用導(dǎo)出類 
  8.         listeners.add(new EchoListener()); 
  9.         // 使用開放類 
  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:通過SPI 
  17.         System.out.println("Demo: SPI Mode"); 
  18.         // 加載所有的IEventListener實(shí)現(xiàn)類,無視其導(dǎo)出/開放與否 
  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)不是問題了,可問題是老的 Java 8 應(yīng)用怎么辦?別著急,我們先來了解兩個(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)的路徑,如果是類路徑,那么就會(huì)轉(zhuǎn)為未命名模塊,如果是模塊路徑,那么就會(huì)轉(zhuǎn)為自動(dòng)模塊。注意,自動(dò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ì)未命名模塊無效,也即多個(gè)未命名模塊可以導(dǎo)出同一個(gè)包,但自動(dòng)模塊不允許。

未命名模塊和自動(dòng)模塊存在的意義在于,無論傳入的 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)在類路徑下,也就是轉(zhuǎn)為未命名模塊,對(duì)于未命名模塊而言,默認(rèn)導(dǎo)出所有包并且依賴所有模塊,因此應(yīng)用可以正常運(yùn)行。進(jìn)一步的解讀可以參閱官方白皮書的相關(guān)章節(jié)。

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

3.1 Bottom-up 自底向上策略

第一種策略,叫做自底向上(bottom-up)策略,即根據(jù) jar 包依賴關(guān)系(如果依賴關(guān)系比較復(fù)雜,可以使用 jdeps 工具進(jìn)行分析),沿著依賴樹自底向上對(duì) jar 包進(jìn)行模塊化改造(在 jar 包的源代碼根目錄下添加合法的模塊描述文件 module-info.java)。初始時(shí),所有 jar 包都是非模塊化的,全部置于類路徑下(轉(zhuǎn)為未命名模塊),應(yīng)用以傳統(tǒng)方式啟動(dòng)。然后,開始自底向上對(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 從類路徑移到了模塊路徑,這個(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),然后從這些根模塊開始根據(jù)模塊依賴關(guān)系在模塊路徑中循環(huán)找出所有可觀察到的模塊(observable module),這些可觀察到的模塊加上類路徑下的 jar 文件最終構(gòu)成了編譯時(shí)環(huán)境和運(yùn)行時(shí)環(huán)境。那么根模塊是如何確定的呢?對(duì)于運(yùn)行時(shí)而言,如果應(yīng)用是通過 -m 方式啟動(dòng)的,那么根模塊就是 -m 指定的主模塊;如果應(yīng)用是通過傳統(tǒng)方式啟動(dòng)的,那么根模塊就是所有的 java.* 模塊即 JRE(參見圖-2)?;氐角懊娴睦樱绻患?--add-modules 參數(shù),那么運(yùn)行時(shí)環(huán)境中除了 JRE 就只有 mod1.jar、mod2a.jar、mod2b.jar,沒有 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 都依賴 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ù)依賴關(guān)系都會(huì)被識(shí)別為可觀察到的模塊并加入到運(yùn)行時(shí)環(huán)境,應(yīng)用可以正常運(yùn)行。

3.2 Top-down 自上而下策略

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

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

還是以示例工程為例,假設(shè) mod4 是一個(gè)第三方 jar 包,無法進(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模塊化策略

看上去很完美,不過等一下,如果有多個(gè)自動(dòng)模塊,并且它們之間存在分裂包呢?前面提到,自動(dòng)模塊和其它命名模塊一樣,需要遵循分裂包規(guī)則。對(duì)于這種情況,如果模塊化改造勢(shì)在必行,要么忍痛割愛精簡(jiǎn)依賴只保留其中的一個(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)行說明,最后詳細(xì)闡述了老版本應(yīng)用模塊化改造的思路?,F(xiàn)在我們?cè)賮砜匆恍└K系統(tǒng)比較相似的框架和工具,以進(jìn)一步加深你對(duì)模塊系統(tǒng)的理解。

4.1 vs OSGi

說起模塊化,尤其在 Java 界,那么肯定繞不過 OSGi 這個(gè)模塊系統(tǒng)的鼻祖。OSGi 里的 bundle 跟模塊系統(tǒng)里的模塊非常相似,都是以 jar 文件的形式存在,每個(gè) bundle 有自己的名稱,也會(huì)定義依賴的 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)下,越來越被邊緣化。

4.2 vs Maven

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

4.3 vs ArchUnit

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

 

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

2017-03-11 22:19:09

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

2020-07-03 08:21:57

Java集合框架

2022-04-07 10:39:21

反射Java安全

2022-06-20 09:01:23

Git插件項(xiàng)目

2023-02-10 09:04:27

2020-02-18 16:20:03

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

2022-08-01 11:33:09

用戶分析標(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

2023-10-17 08:15:28

API前后端分離

2024-09-23 08:00:00

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

2023-11-18 09:30:42

模型AI

2020-11-22 08:32:29

人工智能AI

2022-07-06 12:07:06

Python函數(shù)式編程

2019-04-01 10:43:59

Linux問題故障

2022-05-19 08:28:19

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

2020-10-21 14:12:02

Single Sign

2023-11-06 07:21:13

內(nèi)存結(jié)構(gòu)Jvm
點(diǎn)贊
收藏

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