JPMS的module-info.java

JPMS是java9,准确来说是从jdk11开始使用的一个新的模块化系统,java从这时候开始,除了package之外多了一个叫做module的结构,每一个module有且仅有一个module-info.java 它声明了模块的访问方式以及依赖关系。

module包括一个或者多个package,它描述了这些package哪些允许其他java程序使用,哪些不能,能允许到什么程度,这里大致分为以下几种:

模块中open(开放)的包(或者整个open的模块),这种类型的模块允许其他java使用,允许其他java程序深度反射的操作,所谓深度反射意味着其他java可以完全的反射利用这个module里面的类,包括里面的private类和方法。如果有必要,还可以指定开放给哪一个或者一些module。

如果一个module-info中有如下的声明,open声明在整个module上面,那么这个模块是开放的:


open module Demo {
}

如果module-info中有如下定义,则指定的包是开放的:

module Demo {
   // opens声明在包上面,任意模块都能使用此包的内容,并且允许深度反射它
   opens org.demo.test;
   // opens给example,除此之外的包不能使用它。
   opens org.demo.test to example;
}

export(导出)的模块,这个类型的模块允许其他java应用使用,允许一般的反射,类似于反射private之类的就完全不可以了。export在module-info中只能声明在包上面,不可以声明在模块上面,如果有必要,还可以指定导出给哪一个或者一些module。

module Demo {
    // 声明在包上面的exports,任意其他的模块都能使用此包的内容,但是不能神队反射它的类
    exports org.demo.test;
    // org.demo.example 导出给test模块,其他模块不能用。
    exports org.demo.example to test;
}

auto(自动)类型的模块,这类模块没有编写module-info.java,而是在META-INFO的配置文件里面直接指定module的相关信息,具体来说就是里面的MANIFEST.MF这个文件。

Automatic-Module-Name: 模块名称
Export-Package: 包导出(同 module-info里面的export)
Import-Package: 现在还没说到,同module-info里面的requires

如果一个包含module-info的java模块想要使用其他的java类库或者模块,就必须在module-info里面添加requries语句来导入它们,由于java11开始jdk本身也模块化了,因此一部分系统本身的模块也要在module-info里面使用requres进行导入,例如swing:

module Demo {
    // 加载swing的模块,不加载就不能使用swing
    requires java.desktop;
}

只有这样才能正确的导入需要的类。有些时候,某个类并不是必须的,因此我们可以将requires 改为 requires static,这样java启动的时候就不会检查这个模块了,能够避免ModuleFindException。

除了以上,还有Java的SPI也可以在JPMS的module-info里面声明,也是十分的简单,使用provides关键字即可向SPI的接口提供服务:

module Demo {
   
    // 向SPI的Service接口提供服务的具体实现,也就是SPI,语法是
    // provides [服务接口] with [服务接口的实现]
    provides java.net.spi.URLStreamHandlerProvider with org.demo.CustomURLProviderHandler;
}

如果需要其他的模块给本模块的接口提供SPI服务,那么只需要使用uses关键字。

module Demo {
    // 要求其他模块提供此服务的具体实现。
    uses org.demo.IService;
}

Fantastic Soft

风铃之书是个人的工作和生活的总结和分享的站点,欢迎来访和留言,有时也会提供自家软件的发布版本和开源项目。