本文主要讲述下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
)等几个概念。