Java9的模块化是什么
Java9新特性中的模块化到底是什么
Java9中的一个重大特性是增加了一种新型的程序设计组件 - 模块。
官方对模块的定义为:一个被命名的,代码和数据的自描述集合。( the module, which is a named, self-describing collection of code and data)。
这个在Java7的时候就已经被提出,但由于其复杂性,不断跳票Java7、Java8,直到Java9才姗姗来迟的模块化,到底是什么,在实际coding中又有什么用呢?
我们主要从以下三个方面来分析:
What 模块化是什么
How 模块化怎么用
Why 为什么要用模块化
模块化是什么?
模块是Java9中新增的一个组件,可以简单理解为是package的上级容器,是多个package的集合,一个jar可以有多个module,一个module可以有多个package。从代码结构上看,jar > module > package > class, interface。
Java9的模块通过requires和exports关键字,对自身所依赖(requires)的模块和自身暴露(exports)出去的内容(package)进行了声明。本模块只能使用其他模块暴露(exports)出来的内容(package),其他模块也只能使用本模块暴露(exports)出去的内容(package)。
Java9的模块化和Maven的区别在于Maven管理的是整个jar的依赖,关注的是整体。而模块化管理的是这个jar中的模块需要对外暴露的内容和对外依赖的模块,关注的是细节。maven的依赖是将整个jar都给你了,哪怕你仅仅只需要其中的一个类。模块化的依赖则是更细粒度的package的管理,你只能使用你依赖的模块下被暴露出来的package。
那么,模块化怎么用呢?
我们搭建一个简单的modular-demo项目,分为modular-common,modular-persistent,modular-service,modular-web 4个子项目。
4个子项目的定位为:
modular-common:通用层,主要提供常量类、工具类、枚举类等通用代码。
modular-persistent:持久层,主要提供数据库领域实体domain类,数据操作接口dao。
modular-service:service层,主要提供业务逻辑处理的service及其实现类。
modular-web:web层,主要对外提供api接口,视图渲染,输入输出数据处理等功能。
4个子项目的maven依赖关系为:
modular-persistent依赖modular-common
modular-service依赖modular-persistent
modular-web依赖modular-service
每个项目的代码大致如下:
与传统Maven项目不同的是,每个子项目下面都有着自己的module-info.java,里面声明了项目中的模块暴露出去的包和需要依赖的模块。
注意:我们提到的模块均是指Java9中的模块,不是指maven中的模块,maven中的模块是指可以构建为一个jar或者war的项目,本质是一个项目,所以我们用子项目来表示maven中的模块。每个子项目可以有多个模块,demo中每个子项目只包含了一个模块,但不代表只能有一个模块。
common模块的module-info.java
module modular.demo.common {
// 声明自己对外暴露的包名
exports com.hanmc.example.modulardemo.common;
}
module 后面的modular.demo.common声明了本模块的模块名,是本模块的唯一标识,其它模块可以通过这个标识来声明对这个模块的依赖。
exports com.hanmc.example.modulardemo.common 声明了本模块暴露出去的package,如果所有package都没有暴露,那么其他模块即使依赖了这个模块,也依然无法使用此模块中的代码。
persistent模块的module-info.java
module modular.demo.persistent {
exports com.hanmc.example.modulardemo.persistent.domain;
exports com.hanmc.example.modulardemo.persistent.dao;
//声明需要依赖的模块
requires modular.demo.common;
requires mybatis.plus;
requires mybatis.plus.core;
requires mybatis.plus.annotation;
}
将domain和dao两个package暴露出去,同时声明了对modular-common和mybatis-plus框架中的模块的依赖。
service模块的module-info.java
module modular.demo.service {
exports com.hanmc.example.modulardemo.service;
exports com.hanmc.example.modulardemo.service.impl;
requires modular.demo.persistent;
requires spring.context;
requires spring.beans;
}
将service这个package暴露出去,同时声明了对modular-persistent和spring框架中模块的依赖。
注意:modular-service模块只暴露了com.hanmc.example.modulardemo.service这个package,并没有暴露com.hanmc.example.modulardemo.service.impl这个包,所以外部是无法使用service接口的实现类的,只能通过service接口来调用,对于使用者来说隐藏了具体的实现。
web模块的module-info.java
module modular.demo.web {
requires spring.web;
requires spring.beans;
requires spring.boot;
requires modular.demo.service;
requires modular.demo.persistent;
requires modular.demo.common;
requires org.mybatis.spring;
requires spring.boot.autoconfigure;
//声明com.hanmc.example.modulardemo包对spring开放,允许spring在运行期间通过反射机制访问其代码
opens com.hanmc.example.modulardemo to spring.core, spring.beans, spring.boot, spring.context, spring.web;
}
声明了对spring框架和modular-common、modular-persistent、modular-service的模块的依赖。同时将com.hanmc.example.modulardemo的package开放给spring的模块使用,以便spring在启动时通过反射机制访问项目中的代码来初始化容器。
注意: exports和opens的区别在于,exports导出的包可以在编译和runtime期间访问其public成员。opens声明的包,则还可以在运行期间通过反射来访问其public和private成员。
为什么要用模块化
那么,为什么要用模块化呢,使用模块化有什么好处呢?看起来代码的编写反而更为复杂了!
显式管理依赖:
每个模块需要显式声明自己需暴露的包,而自己所依赖的和自己内部使用的包,则不会暴露,也不会被外部引用到。这种机制彻底的杜绝了Java9以前Jar包依赖买一送一堆的场景,大大的减少Jar包冲突的情况。
场景:比如我的项目中本身已经依赖了hibernate-validator用来做参数校验,在后续的开发中由于加解密需要又引入了一个提供了加解密api的第三方的jar,这个第三方jar也依赖了另外一个版本hibernate-validator,那么在项目中就存在了两个不同版本的hibernate-validator,这个时候就会出现jar包冲突。这个时候模块化就可以完美解决这个问题,这个第三方加解密的jar可以在module-info.java中只exports出本身加解密功能的部分package,而不会exports出这个jar本身所依赖的其他jar包。
强封装性:
模块显式的选择向其他模块只暴露需要的类或接口,而完美的隐藏了内部实现的细节及其他内部成员,实现了真正的封装。
场景:比如下图module-common中的枚举类DefaultResponseEnum,定义了系统内置的几种默认响应码,因为被定义在了inner包中,而inner包又没有被声明exports,所以这个枚举类只能在module-common内部使用,避免了被其他模块直接使用。
安全性:
显式依赖管理及强封装性,大大的减少了程序运行时不必要模块的加载,减少了Java运行期间的被攻击面。代码真正意义上可以按照作者的设计思路进行公开和隐藏,限制了反射的滥用,更好的保护了那些不建议被外部直接使用或过时的内部类。
规范性:
显示的声明暴露的内容,可以让第三方库的开发者更好的管理自己的内部实现逻辑和内部类。第三方库作者可以更轻松的管理自己的内部类的访问权限和反射调用权限,避免了出现sun.misc.BASE64Encoder这些内部类在已经被官方声明了过时和不建议使用的前提下,仍有大量的开发者去随意使用的情况。因为在Java9之前,JDK开发者只能建议,而无法实现强制约束。
场景:比如我们提倡的面向接口编程,要求在controller中只能注入service层的接口,而不能直接注入其实现类,但是这个要求只是个规范,无法强制约束,Java9以前,我们仍然可以在直接注入service层的实现类,代码仍然可以照常运行,只是没那么规范而已。但是在Java9以后,我们可以在service的模块中只exports出接口,这样controller就无法直接注入实现类,在编译期就会报错,实现了强约束。
自定义最小运行时映像:
Java因为其向后兼容的原则,不会轻易对其内容进行删除,包含的陈旧过时的技术也越来越多,导致JDK变得越来越臃肿。而Java9的显示依赖管理使得加载最小所需模块成为了可能,我们可以选择只加载必须的JDK模块,抛弃如java.awt, javax.swing, java.applet等这些用不到的模块。这种机制,大大的减少了运行Java环境所需要的内存资源,在对于嵌入式系统开发或其他硬件资源受限的场景下的开发非常有用。
孵化器模块的支持:
Java9中,引入了孵化器模块,使用了固定的前缀jdk. incubator。孵化器模块是一种提供实验API的机制,相当于是beta版,其中的内容在后续的版本中可能会被改动或删除。这个机制的存在,可以让开发者在明确的知道其不稳定性的同时,如果感兴趣的话,可以尝试提前接触和使用这些实验性的功能,使得这个新功能可以在真实环境中不断打磨完善。
场景:如Java9中提供的jdk. incubator.httpclient模块,提供了一个全新的HttpClient API,并且在Java11中孵化为正式模式 java.net.http,提供了高性能的异步非阻塞调用支持。
本文为个人学习整理,如有描述错误或者对相关内容感兴趣,欢迎评论或私信交流,一起讨论、共同进步。
Java9的模块化是什么的更多相关文章
- JAVA9模块化详解(一)——模块化的定义
JAVA9模块化详解 前言 java9已经出来有一段时间了,今天向大家介绍一下java9的一个重要特性--模块化.模块化系统的主要目的如下: 更可靠的配置,通过制定明确的类的依赖关系代替以前那种易错的 ...
- Java 8新特性探究(八)精简的JRE详解
http://www.importnew.com/14926.html 首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 Java小组 工具资源 - 导航条 - 首页 所有文章 资讯 ...
- java 11 移除的一些其他内容,更简化的编译运行程序,Unicode 10,移除了不太使用的JavaEE模块和CORBA技术,废除Nashorn javascript引擎,不建议使用Pack200 相关api
移除的一些其他内容 移除项 移除了com.sun.awt.AWTUtilities 移除了sun.misc.Unsafe.defineClass, 使用java.lang.invoke.MethodH ...
- JVM核心知识体系(转http://www.cnblogs.com/wxdlut/p/10670871.html)
1.问题 1.如何理解类文件结构布局? 2.如何应用类加载器的工作原理进行将应用辗转腾挪? 3.热部署与热替换有何区别,如何隔离类冲突? 4.JVM如何管理内存,有何内存淘汰机制? 5.JVM执行引擎 ...
- 你离BAT之间,只差这一套Java面试题
最近,各大公司开始了春招,很多人已经开始在准备面试了,特地来总结下初中级程序员应该掌握的面试题目.这篇面试指南,只适用于初中级程序员,其中不涉及分布式等问题.关于中高级的程序员问题,我后面可能再出一篇 ...
- [转帖]Java 8新特性探究(八)精简的JRE详解
Java 8新特性探究(八)精简的JRE详解 https://my.oschina.net/benhaile/blog/211804 精简版的api 撸了今年阿里.网易和美团的面试,我有一个重要发 ...
- Java 11 New Features
前言 北京时间 2018年9 月 26 日,Oracle 官方宣布 Java 11 正式发布.这是 Java 大版本周期变化后的第一个长期支持版本,非常值得关注.从官网即可下载, 最新发布的 Java ...
- 深入理解JVM(③)Java的锁优化
前言 从JDK5到JDK6HotSpot虚拟机开发团队花费了大量的资源实现了各种锁优化技术,如适应性自旋(Adaptive Spinning).锁消除(Lock Elimination).锁膨胀(Lo ...
- Java基础之类加载器
Java类加载器是用户程序和JVM虚拟机之间的桥梁,在Java程序中起了至关重要的作用,理解它有利于我们写出更优雅的程序.本文首先介绍了Java虚拟机加载程序的过程,简述了Java类加载器的加载方式( ...
随机推荐
- 微服务6:通信之网关 Ready
★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 1 概述 回顾下前面几 ...
- 我来教你如何用Docker部署最近火爆的人生重开模拟器
文章目录 获取项目源码包 Dockerfile 构建docker镜像 启动docerk容器 访问liferestart 如果人生可以重来... <可惜没如果> github项目地址:htt ...
- CobaltStrike逆向学习系列(5):Bypass BeaconEye
这是[信安成长计划]的第 5 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 BeaconEye 检测原理 0x02 Bypass 1 0x03 Bypass 2 0x04 效果图 ...
- 关于 Word2Vec 使用时遇到的一系列问题!!
1 训练时 model = Word2Vec(x, size=250, window=5, min_count=5, workers=12, iter=10, sg=1) 这句代码一直报错 查了 ...
- bi数据可视化平台带来的企业变化
相信现在互联网的发展,大家有目共睹,在互联网的快速发展下,所产生的数据已经成为庞然大物,各行各业都在进行数据化转型,大数据分析也就成了香饽饽,bi数据可视化平台能够让数据可视化,通过数据分析可以业务人 ...
- django+vue实现跨域
版本 Django 2.2.3 Python 3.8.8 djangorestframework 3.13.1 django-cors-headers 3.11.0 django实现跨域 说明:此处方 ...
- IDEA安装下载以及使用
IDE 集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器.编译器.调试器和图形用户界面等工具.集成了代 ...
- VS Code 启动占用100%Cpu问题解决办法
打开VS Code之后,点击文件->首选项->设置 search.followSymlinks
- (第一章第五部分)TensorFlow框架之变量OP
系列博客链接: (一)TensorFlow框架介绍:https://www.cnblogs.com/kongweisi/p/11038395.html (二)TensorFlow框架之图与Tensor ...
- python中的流程控制
目录 引言 流程控制的分类 分支结构 单if结构 if与else结构 if与elif与else结构 if分支的嵌套 循环结构 while循环 while + break循环 while + conti ...