潦草白纸

Java 9模块化关键字及应用场景

一、背景

Spring Boot 3.0最低要求jdk17,为跟上节奏储备知识。

二、简介

关键字 描述 应用场景
module 定义一个模块 代码隔离,依赖控制,代码可重用性
open module 定义一个像java9之前的开放模块 像Java的旧版本那样允许完全反射
exports...to 指定模块的一部分对外提供的包 限制代码对外可见性,防止包冲突
requires 指定当前模块依赖的另一个模块 控制依赖,避免冲突,提高系统可靠性
requires static 声明一组模块的静态依赖关系 编译时检查依赖关系,以确保程序在运行时能够正确地工作。这对于使用反射或动态类加载的程序特别有用,因为这些程序在编译时无法检测到某些依赖关系,需要在运行时才能动态地加载类。
opens...to 类似于exports,但是会开放当前模块内的包访问权限,便于反射使用 某些框架、工具需要使用反射机制,但是反射机制需要访问私有成员
uses 指定当前模块使用的服务类型 提供SPI机制支持,方便应用程序扩展
provides ...with 指定当前模块提供的服务类型和实现类 提供SPI机制支持,方便应用程序扩展

Java 9模块化关键字应用场景:

  • module:模块化开发,将代码分成多个模块,隔离不同模块的功能,增加代码可重用性。
  • exports:限制代码对外可见性,防止包冲突,控制API的访问权限。
  • requires:控制依赖,避免冲突,提高系统可靠性。避免类路径的问题,方便模块的重构和管理。
  • opens:提供某些框架、工具需要使用反射机制,但是反射机制需要访问私有成员。
  • uses:提供SPI机制支持,方便应用程序扩展。
  • provides:提供SPI机制支持,方便应用程序扩展。

三、基础声明模块与引用

1. 声明一个模块

module com.example.myapp {
    requires java.base;
    requires com.example.mymodule;
}

上述代码定义了一个名为 com.example.myapp 的模块,该模块依赖于 java.base 和 com.example.mymodule 模块。

2.导出包

module com.example.myapp {
    requires java.base;
    requires com.example.mymodule;
    exports com.example.myapp.api; 
}

上述代码将 com.example.myapp.api 包导出到其他模块中,使其可以访问。

3.开放反射访问

module com.example.myapp {
    requires java.base;
    requires com.example.mymodule;
    opens com.example.myapp.internal to com.example.anothermodule;
}

上述代码将 com.example.myapp.internal 包开放给 com.example.anothermodule 模块,以便其可以使用反射访问该包中的类和方法。

4.使用自定义模块路径

module com.example.myapp {
    requires java.base;
    requires com.example.mymodule;
    exports com.example.myapp.api; 
}

上述代码使用 modules 目录中的模块路径来运行 com.example.myapp.Main 类。

四、SPI声明与引用

1.声明所需服务

uses关键字用于指定模块所需的服务,它可以出现在模块描述文件(module-info.java)中。下面是一个示例:

module com.example.myapp {
    requires java.base;
    requires com.example.mymodule;
    exports com.example.myapp.api; 
}

在上面的示例中,my.module模块依赖于some.module模块,并使用了com.example.service.SomeService服务。

2.对外声明所提供服务

provides关键字用于指定模块提供的服务和实现,它也可以出现在模块描述文件(module-info.java)中。下面是一个示例:

module my.module {
    provides com.example.service.SomeService with com.example.service.impl.MyServiceImpl;
}

在上面的示例中,my.module模块提供了com.example.service.SomeService服务,并使用了com.example.service.impl.MyServiceImpl实现。

使用了provides关键字的模块还需要使用uses关键字来指定所需的服务,例如:

public interface SomeService {
    void sayHello();
}
 
public class MyServiceImplimplements SomeService {
    public static void doSomething() {
        System.out.println("Hello, Modules!");
    }
 
    public void sayHello() {
        System.out.println("Hello!");
    }
}
 
module my.module {
    uses com.example.service.impl.MyServiceImpl;
}
 
Iterable<SomeService> services = ServiceLoader.load(SomeService.class);
SomeService service = services.iterator().next();
service.sayHello();

posted on 2023-05-11 13:37  潦草白纸  阅读(335)  评论(0编辑  收藏  举报

导航