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

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

1.module及modules

module

module主要分如下两种:

  • main module 包含main方法的module,通过—module或者-m指定
  • root module 指定模块系统解析的根模块,从根模块解析模块依赖,可以通过—add-modules mod1,mod2来指定

modules

  • unnamed modulesjava9通过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

  • Modular Programming in Java 9: Build large scale applications using Java modularity and Project Jigsaw

原文发布于微信公众号 - 码匠的流水账(geek_luandun)

原文发表时间:2018-02-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏后端技术探索

​nginx的配置系统

配置文件中以#开始的行,或者是前面有若干空格或者TAB,然后再跟#的行,都被认为是注释,也就是只对编辑查看文件的用户有意义,程序在读取这些注释行的时候,其实际的...

962
来自专栏小程序之家

如何实现小程序与服务器通信

网络请求方式较多,大家可以参考如何在小程序中实现文件上传下载和如何在小程序中实现 WebSocket 通信实现更多与服务器请求。

1.9K5
来自专栏流柯技术学院

selenium + python自动化测试环境搭建

-------------------------------------------------------------

1642
来自专栏散尽浮华

nginx反向代理+缓存开启+url重写+负载均衡(带健康探测)的部署记录

在日常运维工作中,运维人员会时常使用到nginx的反向代理,负载均衡以及缓存等功能来优化web服务性能。 废话不多说,下面对测试环境下的nginx反向代理+缓存...

7889
来自专栏進无尽的文章

基础篇-Mac终端指令大全

在日常开发中我们经常会用到一些Mac的指令在终端中进行操作,所以了解和熟练使用一些基本的Mac终端指令是非常有必要的,也有利于自己的职业发展,下面就简单总结下M...

991
来自专栏后端技术探索

关于PHP脚本和浏览器连接深入解析

当 PHP 脚本正常地运行 NORMAL 状态时,连接为有效。当远程客户端中断连接时,ABORTED 状态的标记将会被打开。远程客户端连接的中断通常是由用户点击...

1961
来自专栏IT技术精选文摘

Nginx核心模块常用指令

配置示例 user www www; worker_processes 2; error_log /var/log/nginx-error.log info; ...

2385
来自专栏L宝宝聊IT

LVS负载均衡群集--NAT模式

1923
来自专栏技术小黑屋

自定义控件进阶:declare-styleable重用attr

最近接触了Android自定义控件,涉及到自定义xml中得属性(attribute),其实也很简单,但是写着写着,发现代码不完美了,就是在attrs.xml这个...

981
来自专栏Django中文社区

登录

用户已经能够在我们的网站注册了,注册就是为了登录,接下来我们为用户提供登录功能。和注册不同的是,Django 已经为我们写好了登录功能的全部代码,我们不必像之前...

7895

扫码关注云+社区

领取腾讯云代金券