前言
對(duì)于模塊的定義,相信小伙伴們都不會(huì)有太大的疑問(wèn),這里引用JDK中模塊的定義:一組可重用的相關(guān)包和資源,以及模塊的描述信息。直白點(diǎn)的描述就是:用一種比package更大級(jí)別的組織方法來(lái)管理我們的類。講到它的作用是組織管理,大家是不是就開(kāi)始聯(lián)想到了OSGi,JBoss Module,Maven,甚至是微服務(wù)呢?首先,這幾種形式都是用于軟件的模塊化方法,只是應(yīng)用的場(chǎng)景和各自的長(zhǎng)處有所不同,指北君用一張圖表來(lái)做一下簡(jiǎn)單對(duì)比:
模塊化方式
- 微服務(wù):服務(wù)粒度的組織方法,比模塊級(jí)別更高
- Maven:依賴管理工具
變化
首先,作為一頭猿,最直接的編碼IDE工具,以Eclipse為例,我們新建一個(gè)標(biāo)準(zhǔn)的Java工程,切換下JDK進(jìn)行對(duì)比,
JDK庫(kù)-JAVA11
JDK庫(kù)-JAVA8
首先我們會(huì)發(fā)現(xiàn):項(xiàng)目使用中的JDK11的庫(kù)中比之前JDK8多出很多條目來(lái),而且和之前的完全不一樣了。這就是JDK引入模塊后,將原來(lái)的庫(kù)進(jìn)行了拆分。為什么要拆呢?
- 伴隨Java的版本升級(jí),包越來(lái)越多,功能越來(lái)越多,組織管理越來(lái)越難
- 一些jar包太大(比如rt.jar),不利于在小型設(shè)備中運(yùn)行
- 無(wú)法定義只能在模塊內(nèi)部訪問(wèn)的接口,只能通過(guò)一些額外的約束,比如文檔,internal等形式進(jìn)行提示
JDK是如何對(duì)原有的jar進(jìn)行拆分的呢?我們查看模塊名稱會(huì)發(fā)現(xiàn),所有模塊分成兩類:java開(kāi)頭和jdk開(kāi)頭,這是按照J(rèn)AVA的JRE和JDK范圍進(jìn)行的大類別的劃分,然后再按照功能級(jí)做進(jìn)一步劃分。除了在開(kāi)發(fā)者環(huán)境中引入的庫(kù)發(fā)生變化外,在JDK的安裝目錄中也有類似的變化
JDK安裝目錄對(duì)比
明顯是jre目錄不在了,增加了jmods目錄,lib下面的組織形式也發(fā)生了較大的變化。
可以做什么
前面我們介紹模塊系統(tǒng)引入后帶來(lái)的直觀的變化,這一節(jié)指北君要介紹模塊系統(tǒng)的作用,我們先來(lái)看一下模塊的定義里面包含的要素:
- 名稱 – 模塊名
- 依賴 - 本模塊依賴的一系列其他模塊
- 公共包 - 外部可訪問(wèn)的所有包
- 提供的服務(wù) - 提供其他模塊消費(fèi)的服務(wù)實(shí)現(xiàn)
- 消費(fèi)的服務(wù) - 允許當(dāng)前模塊作為服務(wù)消費(fèi)者
- 反射權(quán)限 - 顯式允許其他類通過(guò)反射訪問(wèn)的包的私有成員
從定義的要素中我們發(fā)現(xiàn):模塊不僅僅是提供的一直包、類的組織方式,更重要的是提供了以前無(wú)法支持的安全訪問(wèn)控制。
模塊的類型
有四種類型的模塊
- 系統(tǒng)模塊:JDK定義的模塊,可以通過(guò)下面命令來(lái)獲取
java --list-modules
- 應(yīng)用模塊:我們開(kāi)發(fā)的應(yīng)用對(duì)應(yīng)的模塊,通過(guò)module-info.java定義并編譯成對(duì)應(yīng)的class
- 自動(dòng)模塊:通過(guò)模塊路徑加載的第三方j(luò)ar包
- 未命名模塊:不是通過(guò)模塊路徑加載的第三方j(luò)ar
模塊的聲明
要?jiǎng)?chuàng)建一個(gè)模塊,需要在包的根路徑下創(chuàng)建module-info.java(注意名稱是固定的),如果按照Class的方式創(chuàng)建會(huì)出現(xiàn)名稱校驗(yàn)失敗,這時(shí)候可以直接創(chuàng)建一個(gè)文件命名為module-info.java。
module moduleName {
}
使用關(guān)鍵字module定義,模塊名稱按照約定為通過(guò)點(diǎn)號(hào)"."分割的小寫(xiě)詞組,比如java.base, north.sample。
requires
requires用來(lái)管理模塊的依賴關(guān)系,我們一旦采用了模塊,我們會(huì)發(fā)現(xiàn)原來(lái)的有些類會(huì)出現(xiàn)編譯錯(cuò)誤,這是因?yàn)槲覀兊拇a中應(yīng)用了默認(rèn)之外的包,需要通過(guò)requires關(guān)鍵詞引入我們引用的模塊。
module north.smaple{
requires java.scripting;
}
使用requires還可以使用兩個(gè)修飾詞:static,transitive,
- static用來(lái)定義一個(gè)可選的模塊依賴,僅當(dāng)編譯時(shí)有依賴才引用
- transitive 表示下游的模塊不用顯式聲明,就可以使用上級(jí)模塊中通過(guò)transitive關(guān)鍵字引入的模塊
exports
通過(guò)exports我們可以定義可訪問(wèn)的接口
module north.smaple{
exports north.jdk.scripting;
}
我們還可以通過(guò)exports…to來(lái)定義接口開(kāi)放的目標(biāo)對(duì)象。
uses
定義使用的服務(wù),以java.sql模塊代碼為例:
module java.sql {
...
exports java.sql;
exports javax.sql;
uses java.sql.Driver;
}
為什么對(duì)服務(wù)特殊處理呢?各位小伙伴是不是覺(jué)得:requires就能夠定義訪問(wèn)依賴,為啥還要用uses呢?這是因?yàn)椋瑄ses相對(duì)于requires是存在區(qū)別的。比如,我們的服務(wù)接口實(shí)現(xiàn)和服務(wù)接口不在同一個(gè)模塊中,如果用requires則需要對(duì)所有的實(shí)現(xiàn)模塊引入,如果使用uses只需要引入接口所在的模塊就行了,是不是很方便呢!而且有時(shí)我們都不知道接口的實(shí)現(xiàn)模塊,這時(shí)候都無(wú)法通過(guò)requires引入。
provide
如果需要定義外部可使用的服務(wù),則通過(guò)provide聲明,語(yǔ)法是 provides <服務(wù)接口> with <服務(wù)實(shí)現(xiàn)>
module north.smaple{
provides ISampleService with ISampleServiceImpl;
}
open/opens
open是用來(lái)定義模塊的被外部模塊通過(guò)反射調(diào)用的權(quán)限,在這之前我們可以通過(guò)反射調(diào)用任何我們想要訪問(wèn)的類型和成員,甚至是私有屬性的。在使用模塊系統(tǒng)后,如果我們要保持之前的全訪問(wèn),可以直接在module前添加open關(guān)鍵字。
open module north.smaple{
...
}
如果我們有針對(duì)性的開(kāi)放反射權(quán)限,則通過(guò)opens
module north.smaple{
opens north.jdk.scripting;
}
opens還支持更嚴(yán)格的定義 opens ... to ...
總結(jié)
關(guān)于Java的模塊系統(tǒng),我們今天就學(xué)習(xí)到這里,相信經(jīng)過(guò)代碼示例和講解,各位小伙伴已經(jīng)可以將模塊系統(tǒng)應(yīng)用到項(xiàng)目中了。
-
模塊
+關(guān)注
關(guān)注
7文章
2783瀏覽量
49642 -
JAVA
+關(guān)注
關(guān)注
20文章
2985瀏覽量
106950 -
軟件
+關(guān)注
關(guān)注
69文章
5121瀏覽量
88962 -
編碼
+關(guān)注
關(guān)注
6文章
967瀏覽量
55513
發(fā)布評(píng)論請(qǐng)先 登錄
Java Security的核心模塊和代碼演示
基于JAVA與SSM的移動(dòng)電源租賃系統(tǒng)的設(shè)計(jì)
Java語(yǔ)言基礎(chǔ)
基于JAVA的ICQ系統(tǒng)的源代碼
JAVA制作的ICQ系統(tǒng)
模塊化Java:動(dòng)態(tài)模塊化
JAVA常用系統(tǒng)類的使用 實(shí)驗(yàn)
Java 9的新特性總結(jié)

java中數(shù)組的三種定義方式_java中數(shù)組的定義及使用方法(推薦)
Java、SSM移動(dòng)電源租賃系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)

評(píng)論