Project Jigsaw實現了什么:正如我之前解釋的,Jigsaw項目解決了整個Java API用作單個整體代碼庫的問題。 以下幾點突出了主要優點。
1.依賴關系圖 :Jigsaw提供了一種方法,可以唯一地標識特定的代碼庫,還可以聲明代碼庫對其他代碼庫的依賴關系。 這將為一組特定的類創建一個完整的依賴圖。 例如,您要編寫一個依賴于Apache BCEL庫的程序。 到目前為止,您還沒有辦法在代碼本身中表達此要求。 使用Jigsaw,您可以在代碼本身中表達此要求,從而允許工具解決此依賴性。
2.同一代碼的多個版本 :假設您編寫了一個同時依賴libray A和庫B的程序。現在假設庫A依賴于庫C的版本1.0,庫B依賴于庫C的版本2.0。在當前的Java中在運行時,如果不創建自定義類加載器的復雜層次結構,就無法同時使用庫A和B,即使這在所有情況下都行不通。 在Jigsaw成為Java的一部分之后,這就不成問題了,因為一個類將只能看到其依賴類的版本,這些依賴類是類容器模塊所需的模塊版本的一部分。 也就是說,由于模塊A依賴于模塊C的版本1.0,而模塊B依賴于模塊C的版本2.0,因此Java運行時可以確定模塊A或模塊可以看到模塊C中的類的哪個版本。 B.這類似于OSGi項目。
3. Java平臺本身的模塊化 :當前的Java平臺API龐大,并非每種情況下它的所有部分都相關。 例如,旨在運行Java EE服務器的Java平臺不必實現Swing API,因為這沒有任何意義。 同樣,嵌入式環境可以精簡一些不太重要的API(對于嵌入式),例如編譯器API,以使其更小,更快。 在當前的Java平臺下,這是不可能的,因為任何經過認證的Java平臺都必須實現所有API。 拼圖將提供一種僅實現與??特定平臺相關的API集的一部分的方法。 由于模塊可以顯式聲明其對任何特定Java API模塊的依賴關系,因此只有在平臺具有該模塊所要求的模塊的實現時,該模塊才會運行。
4.與OS本機安裝集成 :由于模塊系統與現代操作系統中當前可用于安裝程序和庫的模塊系統非常相似,因此可以將Java模塊與這些系統集成。 這些實際上不在Jigsaw項目本身的范圍內,但鼓勵OS供應商啟用它,并且他們很可能會這樣做。 例如,可以輕松地增強基于Redhat的linux系統中可用的基于rpm的存儲庫系統和基于Debian的linux系統中可用的基于apt的存儲庫系統,以支持java模塊系統。
5.模塊入口點 :Java模塊可以指定入口點類,就像jars可以指定它一樣。 運行模塊時,將調用入口點的main方法。 現在,由于操作系統現在可以安裝Java模塊并且可以執行Java模塊,因此它與安裝操作系統的本機程序非常相似。
5.效率 :目前,每次運行JVM時,它都會驗證程序運行期間加載的每個單個類的完整性。 這需要花費大量時間。 此外,還可以從OS文件系統單獨訪問類。 由于可以在運行之前安裝模塊,因此安裝本身現在可以包含驗證步驟,從而無需在運行時驗證類。 這將導致相當大的性能改進。 而且,模塊系統可以以其自己的優化方式存儲類,從而進一步提高性能。
6.模塊抽象 :可以為特定模塊提供抽象。 說模塊A依賴于模塊X。現在,模塊D可以提供模塊X,從而提供其實現。 例如,Apache Xerces模塊將要提供jdk.jaxp模塊,并且能夠滿足jdk.jaxp的依賴關系要求。
模塊化代碼庫的基礎:上面的所有討論都非常模糊,沒有模塊化代碼庫及其用法的真實示例。 模塊化代碼庫可以是單個模塊或多個模塊。 對于單個模塊,我們需要啟用模塊是在任何包外部的源路徑的基礎上創建一個名為module-info.java的文件。 module-info.java文件是以特殊語法編寫的特殊Java文件,旨在聲明模塊信息。 以下是此類mdoule-info.java的示例。
module com.a @ 1.0{requires com.b @ 1.0;class com.a.Hello;
}
在這種情況下,該模塊名為com.a,并且它對com.b有依賴性。 它還聲明了一個入口點com.a.Hello。 請注意,雖然這可能是最佳做法,但并不要求程序包結構必須在模塊名后加上模塊名。
現在您可能會想,如果它是單個模塊模式,那么為什么要依賴于另一個模塊,卻不能使它成為兩個模塊。 請注意,即使只有一個顯式聲明依賴模塊,對所有Java API模塊也存在隱式依賴。 如果沒有將Java API模塊明確聲明為依賴項,則將全部包含。 它仍然是單個模塊的唯一原因是com.b必須在模塊庫中以二進制形式可用。 同時編譯多個模塊時的多模塊。 在單個模塊中編譯源代碼就像我們編譯非模塊化源代碼一樣簡單。 唯一的區別是module-info.java將出現在源根目錄中。
多模塊源:如果源包含多個模塊,則必須為它們提供目錄結構。 它非常簡單。 特定模塊下的源必須保存在模塊名稱的目錄中。 例如,模塊com.a中com.a.Hello類的源必須保存在[source-root] /com.a/com/a/Hello.java中,而模塊-info.java必須保留在目錄[source-root] /com.a中
編譯多模塊源:為此,讓我們考慮一個編譯兩個模塊com.a和com.b的示例。 讓我們首先看一下目錄結構。 如下:
classes
src|--com.a| |--module-info.java| |--com| |--a| |--Hello.java|--com.b|--module-info.java|--com|--b|--Printer.java
com.a中module-info.java的代碼將像這樣。
module com.a @ 1.0{requires com.b @ 1.0;class com.a.Hello;
}
com.b中的module-info.java
module com.b @ 1.0{exports com.b;
}
com.b / com / b中的Printer.java
package com.b;public class Printer{public static void print(String toPrint){System.out.println(toPrint);}
}
com.a / com / a中的Hello.java
package com.a;
import com.b.Printer;public class Hello{public static void main(String [] args){Printer.print("Hello World!");}
}
這些代碼很容易解釋,我們嘗試使用模塊com.a中com.a.Hello類中的模塊com.b中的com.b.Printer類。 為此,com.a module-info.java必須使用Requires關鍵字將com.b聲明為依賴項。 我們正在嘗試在classes目錄中創建輸出類文件。 下面的javac命令可以做到這一點。
javac -d classes -modulepath classes -sourcepath src `find src -name '*.java'`
請注意,我們在backquotes(`)中使用了find命令,以便該命令的輸出將包含在文件列表中。 這將在linux和unix環境中工作。 在其他情況下,我們可以簡單地輸入文件列表。
編譯后,classes目錄將具有類似的類結構。 現在,我們可以使用jmod命令安裝模塊。
jmod create -L mlib
jmod install -L mlib classes com.b
jmod install -L mlib classes com.a
我們首先創建了一個模塊庫mlib,并將模塊安裝在該庫中。 通過在jmod中不為install命令指定-L選項,我們也可以使用默認庫。
現在我們可以簡單地使用以下命令運行模塊com.a
java -L mlib -m com.a
在這里我們也可以使用默認模塊。 還可以創建可直接安裝的可分發模塊軟件包(相當于今天的分發機制中的jar)。 例如,以下將為com.a創建com.a@1.0.jmod
jpkg -m classes/com.a jmod com.a
我試圖在即將發布的Java版本中概述模塊基礎結構。 但是項目Jigsaw每天都在進行修改,并且最終可能完全不同。 但是,預計基本概念將保持不變。 整個模塊的概念更加復雜,我將在下一篇文章中詳細介紹。
參考: Java 8中的烹飪方法–來自JCG合作伙伴 Debasish Ray Chawdhuri的Jigsaw項目 ,位于Geeky Articles博客上。
翻譯自: https://www.javacodegeeks.com/2012/05/whats-cooking-in-java-8-project-jigsaw.html