本文主要講述下java9的模塊系統的必知必會的知識點。java
module主要分以下兩種:
包含main方法的module,經過--module或者-m指定api
指定模塊系統解析的根模塊,從根模塊解析模塊依賴,能夠經過--add-modules mod1,mod2來指定框架
java9經過unnamed modules來支持非java9編寫的代碼,所以遺留代碼就能夠不用升級使用模塊系統,固然最好的方式是升級到支持模塊系統。當模塊系統須要加載在其餘模塊定義的類型時,會嘗試從類路徑加載,若是加載成功,則會納入unnamed modules。unnamed modules會聲明依賴全部的named module,且exports本身的全部包,可是一個named module不能聲明依賴unnamed module。若是一個package在named和unnamed模塊中都有定義,則使用named中的package。ide
它是顯式聲明的named module與類路徑下jar包的橋接,它從一個沒有模塊聲明的jar包中隱式建立,模塊名取自MANIFEST.MF文件中的Automatic-Module-Name屬性或者jar包名字(按必定規則從jar包名稱提取
)。這樣named modules就可使用它來聲明依賴。(須要在javac編譯時使用--module-path指定這些jar的路徑
)一個automatic modules會聲明依賴全部named和unnamed module,而後導出全部package,另外對其餘automatic module支持傳遞依賴ui
聲明依賴
若是A依賴B,B依賴C,B方法返回的類型是C中的類型,那麼須要A也可使用C,則須要在A中聲明依賴C。不過這樣子很是費勁,因此java9內置了個transitive關鍵字。
在B聲明依賴的時候,指定傳遞依賴.net
module B { requires transitive C; exports func.b; }
這樣A無需顯示requires模塊C就可使用C的類型了
聲明這個依賴是編譯時須要,運行時optional。比較適用於框架或類庫,好比jdbc驅動,編譯時僅僅須要api,運行時添加所需的指定類庫,若是不用static,則編譯時就須要把全部支持的jdbc驅動都聲明依賴,這樣比較費勁。code
導出依賴接口
module A { exports modulea.funcB to B; exports modulea.funcC to C,D,E; }
指定導出的modulea.funcB僅對B模塊可見
指定導出的modulea.funcC僅對C,D,E這三個模塊可見
module demo { opens func1; opens func2 to func3; }
在模塊聲明中容許(指定模塊)在運行時使用反射訪問
open module編譯時僅限於指定的導出模塊可用,可是在runtime時容許全部包反射使用(包括private類型和成員
)。open語法主要用於向後兼容,不少遺留代碼都使用反射get
主要在module-info.java描述本模塊是要使用哪一個service接口或者提供了哪一個service的實現。
用於聲明須要的service的接口,這樣就可使用ServiceLoader.load方法去加載依賴中的service providerit
module com.demo.consumer { requires com.example.data; uses com.example.data.SortService; }
這裏的uses代表該模塊須要使用/消費SortService這個接口
module service.sort.bubble { requires service.sort; provides com.example.data.SortService with sort.impl.bubble.BubbleSort; }
這個module使用provides和with聲明瞭是SortService的服務提供方,好讓模塊系統知道這個模塊提供了該接口的實現。注意這裏不須要exports這個實現類
➜ ~ java -d java.logging java.logging@9 exports java.util.logging requires java.base mandated provides jdk.internal.logger.DefaultLoggerFinder with sun.util.logging.internal.LoggingProviderImpl contains sun.net.www.protocol.http.logging contains sun.util.logging.internal contains sun.util.logging.resources
contains:這部分是模塊中包含的但沒有導出的部分(internal
)mandated:java.lang,java.io,java.util等都在這個java.base模塊裏頭,它是其餘模塊的基礎,不用特殊聲明對它的依賴,默認全部模塊都依賴它。所以這裏查看模塊描述時,能夠看到java.base後面跟着一個mandated,表示這個是默認依賴
java9的模塊系統聲明模塊主要有module,requires(transitive\static
),exports,open(package\module
)及service(uses\provides with
)等幾個概念。