leftso 1397 0 2018-08-25 08:09:37

logo-cover-Java 9 模块化编程
JPMS(Java平台模块系统)是Java 9的主要增强功能。它也被称为Project Jigsaw。 在这个Java 9模块示例中,我们将了解模块(一般)以及将来开始编写模块化代码时编程风格的变化。
 

什么是常规模块化?

在任何编程语言中,模块都是(包类似的)工件,包含代码,元数据描述模块以及它与其他模块的关系。 理想情况下,这些工件在编译时可以通过运行时识别。 任何应用程序通常是多个模块的组合,它们一起工作以执行业务目标。

在应用程序体系结构方面,模块应代表特定的业务功能。 它应该是自给自足的,并且应该只公开接口以使用模块功能。 要完成其任务,它可能依赖于其应明确声明的其他模块。

因此,简而言之,一个模块应该遵循三个核心原则 -
  • 强封装

    封装意味着隐藏实现细节,这对于了解正确使用模块并不重要。 目的是封装的代码可以自由地改变而不影响模块的用户。
  • 稳定的抽象

    抽象有助于使用接口(即公共API)公开模块功能。 任何时候,您想要更改模块代码中的业务逻辑或实现,更改将对模块用户透明。
  • 显式依赖

    模块也可以依赖于其他模块。 这些外部依赖项必须是模块定义本身的一部分。 模块之间的这些依赖关系通常表示为图形。 在应用程序级别看到图形后,您将更好地了解应用程序的体系结构。
 

Java 9模块简介

在Java 9之前,您已根据业务功能将“包”分组到相关类。 除了包之外,您还有“访问修饰符”来控制可见的内容以及隐藏到其他类或包的内容。 到目前为止它一直很好用。 Java对封装和抽象有很强的支持。

但是,明确的依赖性是事情开始分崩离析的地方。 在java中,依赖项使用'import'语句声明; 但它们是严格的“编译时间”构造。 编译代码后,没有机制可以清楚地说明它的运行时依赖性。 实际上,java运行时依赖性解析是一个很成问题的领域,因此已经创建了特殊工具来解决这个问题。 gradle或maven。 此外,很少有框架开始捆绑它们的完整运行时依赖性,例如 Spring启动项目。

使用新的Java 9模块,我们将能够更好地编写结构良好的应用程序。 此增强功能分为两个区域:
  1. 模块化JDK本身。
  2. 为其他应用程序提供模块系统。
Java 9 Module System有一个“ java.base ”模块。它被称为基本模块。它是一个独立模块,不依赖于任何其他模块。默认情况下,所有其他模块都依赖于“ java.base ”。
在java 9中,模块可以帮助您封装包和管理依赖项。通常,
  • 类是字段和方法的容器
  • 包是类和接口的容器
  • 模块是包的容器
如果您不知道要查找的具体内容,那么普通代码和模块化代码之间不会有任何重大区别。例如
  1. 模块通常只是一个module-info.class在根目录下有文件的jar文件。
  2. 要使用模块,请将jar文件包含在内modulepath而不是classpath。添加到类路径的模块化jar文件是普通的jar文件,module-info.class文件将被忽略。

如何编写模块化代码

阅读完所有上述概念后,让我们看看模块化代码是如何在现实中编写的。我正在使用Netbeans IDE,因为它早期支持Java 9(截至今天)。

创建Java模块化项目

创建新的模块化项目。我用名字创建了JavaAppOne
创建Java模块化项目
创建Java模块化项目
创建Java模块化项目 - 第2步
创建Java模块化项目 - 第2步

创建Java模块

现在在此项目中添加一个或两个模块。
创建新模块
创建新模块

我添加了两个模块helloworldtest。让我们看看他们的代码和项目结构。

Java 9模块项目结构
$title(/helloworld/module-info.java)
module helloworld {
}
$title(HelloWorldApp.java)
public class HelloWorldApp {
    public static void sayHello() {
        System.out.println("Hello from HelloWorldApp");
    }
}
$title(/test/module-info.java)
module test {
}
$title(TestApp.java)
public class TestApp {
    public static void main(String[] args) {
        //其他代码
    }
}
到目前为止,模块是独立的。现在假设,我们想HelloWorldApp.sayHello()TestApp课堂上使用方法。如果您尝试在不导入模块的情况下使用该类,则会出现编译时错误“package com.howtodoinjava.demo不可见”。

导出包和导入模块

为了能够导入HelloWorldApp,您必须首先从helloworld模块导出'com.howtodoinjava.demo'包,然后helloworldtest模块中包含模块。
module helloworld {
    exports com.howtodoinjava.demo;
}
 
module test {
    requires helloworld;
}
在上面的代码中,requireskeyword表示依赖关系,exports关键字标识可以导出到其他模块的包。只有在显式导出包时,才能从其他模块访问它。默认情况下,其他模块无法访问未导出的模块内的包。
现在,您将能够HelloWorldAppTestApp类中使用类。
$title(TestApp.java)
public class TestApp {
    public static void main(String[] args) {
        HelloWorldApp.sayHello();
    }
}
$title(输出)
Hello from HelloWorldApp
让我们看一下模块关系图
模块图
模块关系图
 
从Java 9日开始,public意味着public只有该模块内的所有其他包。仅当public导出包含该类型的包时,才能由其他模块使用。
 

概要

模块化应用程序具有许多优点,当您遇到具有非模块化代码库的应用程序时,您会更加欣赏它们。你一定听过像“ 意大利面条建筑 ”或“ 凌乱的巨石 ” 这样的术语。模块化不是一个灵丹妙药,但它是一种架构原则,可以在正确应用时高度防止这些问题。
使用JPMS,Java已经迈出了重要的一步,成为模块化语言。无论是对还是错的决定,只有时间会证明。有趣的是,第三方库和框架如何适应和使用模块系统。它将如何影响开发工作,我们每天都在做。