美文网首页Java
java9系列(三)模块系统精要

java9系列(三)模块系统精要

作者: go4it | 来源:发表于2018-02-24 15:37 被阅读24次

    本文主要讲述下java9的模块系统的必知必会的知识点。

    1.module及modules

    module

    module主要分如下两种:

    • main module
      包含main方法的module,通过--module或者-m指定

    • root module
      指定模块系统解析的根模块,从根模块解析模块依赖,可以通过--add-modules mod1,mod2来指定

    modules

    • unnamed modules

    java9通过unnamed modules来支持非java9编写的代码,因此遗留代码就可以不用升级使用模块系统,当然最好的方式是升级到支持模块系统。

    当模块系统需要加载在其他模块定义的类型时,会尝试从类路径加载,如果加载成功,则会归入unnamed modules。unnamed modules会声明依赖所有的named module,且exports自己的所有包,但是一个named module不能声明依赖unnamed module。如果一个package在named和unnamed模块中都有定义,则使用named中的package。

    • automatic modules

    它是显式声明的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支持传递依赖

    2.requires

    声明依赖

    transitive

    如果A依赖B,B依赖C,B方法返回的类型是C中的类型,那么需要A也可以使用C,则需要在A中声明依赖C。不过这样子非常费劲,所以java9内置了个transitive关键字。
    在B声明依赖的时候,指定传递依赖

    module B {
        requires transitive C;
        exports func.b;
    }
    

    这样A无需显示requires模块C就可以使用C的类型了

    static

    声明这个依赖是编译时需要,运行时optional。比较适用于框架或类库,比如jdbc驱动,编译时仅仅需要api,运行时添加所需的指定类库,如果不用static,则编译时就需要把所有支持的jdbc驱动都声明依赖,这样比较费劲。

    3.exports

    导出依赖

    指定可见模块

    module A {
        exports modulea.funcB to B;
        exports modulea.funcC to C,D,E;
    }
    

    指定导出的modulea.funcB仅对B模块可见
    指定导出的modulea.funcC仅对C,D,E这三个模块可见

    4.open

    open package

    module demo {
        opens func1;
        opens func2 to func3;
    }
    

    在模块声明中允许(指定模块)在运行时使用反射访问

    open module

    open module编译时仅限于指定的导出模块可用,但是在runtime时允许所有包反射使用(包括private类型和成员)。

    open语法主要用于向后兼容,很多遗留代码都使用反射

    5.service loader

    主要在module-info.java描述本模块是要使用哪个service接口或者提供了哪个service的实现。

    use

    用于声明需要的service的接口,这样就可以使用ServiceLoader.load方法去加载依赖中的service provider

    module com.demo.consumer {
        requires com.example.data;
        uses com.example.data.SortService;
    }
    

    这里的uses表明该模块需要使用/消费SortService这个接口

    provides with

    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)等几个概念。

    doc

    相关文章

      网友评论

      • qwfys:写的太好了,看了你的博文终于搞明白了module中这些关键字代表什么意思了。

      本文标题:java9系列(三)模块系统精要

      本文链接:https://www.haomeiwen.com/subject/heoqxftx.html