加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 网站设计 > 教程 > 正文

初识Java 9模块化编程

发布时间:2018-08-20 04:40:37 所属栏目:教程 来源:周明耀
导读:副标题#e# 技术沙龙 | 邀您于8月25日与国美/AWS/转转三位专家共同探讨小程序电商实战 【51CTO.com原创稿件】本文是Java9系列文章的第一篇,我会通过几篇文章系统性地介绍Java9的新特性。Java9的发布对于Java语言来说是新的开始,希望Java能够一直走下去,因
副标题[/!--empirenews.page--] 技术沙龙 | 邀您于8月25日与国美/AWS/转转三位专家共同探讨小程序电商实战

【51CTO.com原创稿件】本文是Java9系列文章的第一篇,我会通过几篇文章系统性地介绍Java9的新特性。Java9的发布对于Java语言来说是新的开始,希望Java能够一直走下去,因为它是太多程序员赖以为生的编程工具。

Java9

一、模块化问题

我一直认为,Java这门编程语言已经不再仅仅是一门语言,它是一个由使用者根据自身工程需要所构建起来的生态环境。既然是生态环境,它必然需要根据外部环境的变化不断调整自己,不断地吸收外部优良的设计方案,以用来不断地加强自身,也必然需要不断地改变扩大自己的范围,这样也就不再仅仅局限于语言本身。

我们学习模块化编程之前,应该想想为什么Java需要引入模块化设计思维?首先让我们看看自己打包的jar文件。我们每天在构建的应用程序,也许大家编码是基于某种框架,例如Spring Cloud,基于Spring Cloud可以很方便地启动微服务应用,但是Spring Cloud背后引用了大量的Java生态环境里的第三方库。

长期来看,应用程序如果缺乏结构化设计思维,最终一定会付出代价。回到刚才的问题,模块化编程为什么会出现?因为它的出现可以让我们更为简便、有效地管理库之间的依赖关系,进而减少了工程的复杂度。大家要问了,不是有Maven可以实现这样的功能吗?对的,Maven确实可以,现在Java在JDK库内设计思维上吸收了Maven的设计思维优点,这样JDK内部也有了模块化设计。

需要注意的是,模块化编程并不是一下子出现的,它会出现首先是基于Java本身就是面向抽象编程的,也就是说,模块化编程是构建在抽象层之上的。相较于Java8引入的lambda表达式,模块化编程关注的是整个应用程序的结构扩展问题,而lambda表达式更多的是提供了在一个类里面切换到lambda的方式。模块化带来的影响涉及到设计、编译、打包、部署等等,所以我前面讲了,它不仅仅是一个语言级的特性变化,它的意义比lambda表达式的引入大很多。

开始全文前最后一个问题,为什么JDK9一再推迟发布时间?JDK9的模块化工程为了达到预期目标,即功能之间的边界清晰目标,同时又要保持向后兼容、模块内定义良好且可读,这些多重要求导致了JDK9的长时间难产。这就好比我们编写的应用程序工程,通过20年的积累,成为了一个巨大无比的工程,这时候你再想把它按照模块切分,难度就非常高了。

Java语言已经积累了20年,现在才开始做模块化设计,其实是有点晚了,但是一旦做成了这件事情(JDK9的模块化),后续的模块化进程就会变得快速起来,这也就是为什么可能半年后你就会发现JDK10发布了。

二、模块化编程

1. 什么是模块化编程

什么是模块化编程?模块化编程是将原有的系统分解为若干个自己管理的模块,但是这些模块之间又是互相通信(连接)的。模块,或者可以称之为组件,也就成了一个个可以识别的独立物件,它们可以包括代码、元数据描述,以及和其他模块之间的关系等。理想地看,这些物件从编译时期开始就是可以被识别的,生命周期贯穿整个运行时。这样也就可以想象了,我们的应用程序在运行时应该是由多个模块组成的。

作为一个Java模块,必须满足三个基本要求:

(1) 强封装性

对于封装的重要性应该不用和大家解释了,两个模块之间仅需要知道对方的封装接口、参数、返回值,而对于它内部的实现细节,其他调用方并不关心,内部怎么变化都没关系,只要能够继续调用并返回正确的值就行。

(2) 定义良好的接口

这里包含两层意思。一是模块之间的边界要划分清楚,不能存在重复的部分,二是对于无法封装的公开代码,如果进行了破坏性的修改,那么对其他调用方来说也是破坏性的,因此需要提供定义良好并且稳定的接口给其他调用模块调用。

(3) 显式依赖

这是点和面的关系。每一个点代表一个模块,两点之间的线代表模块之间的依赖关系,所有点就组成了模块调用关系图。只有拥有清晰的模块调用关系图,我们才能确保调用关系的正确性和模块配置的可用性。Java9之前,我们可以采用maven来帮助管理外部依赖关系。

模块化带来的是灵活、可理解、可重用这三大优点。模块化编程和当今很多软件架构概念是类同的,都是为了解决相似的抽象层问题,例如基于组件的开发、面向服务系统架构,或者更新的微服务架构。

前面提到了三个基本要求,强封装性、定义良好的接口、显式依赖,其实在Java9之前就已经支持了。比如封装,类型的封装可以通过使用包和访问修饰符(例如public、protected、private)的组合方式完成。例如protected,只有在同一个包内的类才能访问protected类里面的方法。这里你就可以提出一个问题来了。

如果我们想要让一些包外的类可以访问protected类,又不想让另外一些包外的类可以访问,这时候应该怎么处理呢?Java9之前没有很好的解决方案。对于第二个要求,定义良好的接口,这一点Java语言一直做得不错,从一开始就做得不错。你会发现接口方式在整个模块化编程中扮演了中心角色。

对于显式依赖,由于Java提供的import关键字所引入的jar包需要在编译时才会真正加载,当你把代码打入jar包的时候,你并不知道哪一个jar文件包含了你的jar包需要运行的类型。为了解决这个问题,我们可以利用一些外部工具,例如Maven、OSGi。Java9虽然从jvm核心层和语言层解决了依赖控制问题,但是Maven、OSGi还是有用武之地的,它们可以基于Java模块化编程平台之上继续持续自己的依赖管理工作。

应用程序的jar包关系图

图1:应用程序的jar包关系图

上面这张图包含了两个部分,一部分是应用程序,包含Application.jar的应用程序jar包、该jar包的两个依赖库(Google Guava和Hibernate Validator),以及三个外部依赖jar包。我们可以通过maven工具完成库之间的依赖关系绑定功能。

Java9出现之前,Java运行时还需要包含rt.jar,如上图所示。从这张图上至少可以看出没有强有力的封装概念,为什么这么说?以Guava库为例,它内部的一些类是真的需要被Application.jar工程使用的,但是有一些类是不需要被使用的,但是由于这些类的访问限制符也是public的,所以外部包里的类是可以访问到的,所以说没有履行Java9的封装要求。

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读