为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Java 类路径执行 Java 9+ 服务

使用 Java 类路径执行 Java 9+ 服务

慕尼黑的夜晚无繁华 2023-10-13 16:35:22
我创建了一个简单的 Java9 服务示例,其中包含一个服务接口、两个服务实现以及一个使用 ServiceLoader 的驱动程序。我能够使用 module-path 成功执行该示例,但是当我尝试使用 java -cp (classpath) 执行相同的示例时,我没有得到任何输出,甚至没有任何错误。目录结构out├── driver│   ├── com│   │   └── company│   │       └── driver│   │           └── driver.class│   └── module-info.class├── firstServiceImpl│   ├── com│   │   └── company│   │       └── first│   │           └── serviceImpl│   │               └── FunImpl1.class│   └── module-info.class├── secondServiceImpl│   ├── com│   │   └── company│   │       └── second│   │           └── serviceImpl│   │               └── FunImpl2.class│   └── module-info.class└── serviceInterface    ├── com    │   └── company    │       └── service    │           └── Fun.class    └── module-info.class编译命令javac -d out --module-source-path src src/driver/driver.java src/firstServiceImpl/FunImpl1.java src/secondServiceImpl/FunImpl2.java src/serviceInterface/Fun.java上面的命令使用module-source-path编译代码。运行命令java -cp out/driver:out/serviceInterface/:out/firstServiceImpl/ com.sunil.driver.driver上面的命令使用classpath运行代码。使用module-source-path编译并使用classpath运行代码后。我没有收到任何错误或输出。请帮助我理解为什么使用classpath运行时没有输出。
查看完整描述

1 回答

?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

服务提供者的定位方式取决于服务提供者是否位于类路径或模块路径上。这在以下文档中进行了描述ServiceLoader

将服务提供者部署为模块

在模块中开发的服务提供者必须在模块声明中的provided指令中指定。Provides 指令指定了服务和服务提供者;当另一个带有该服务的use指令的模块获取该服务的服务加载器时,这有助于定位提供者。强烈建议模块不要导出包含服务提供者的包。不支持模块在提供指令中指定另一个模块中的服务提供者。

[...]

在类路径上部署服务提供者

打包为类路径的 JAR 文件的服务提供者通过将提供者配置文件放置在资源目录中来标识META-INF/services。提供程序配置文件的名称是服务的完全限定二进制名称。提供者配置文件包含服务提供者的完全限定二进制名称列表,每行一个。

[...]

基本上,如果您希望能够加载服务提供程序,无论它是否放置在类路径或模块路径上,您都需要在文件中指定指令并provides在. 您还必须确保使用正确的方法来加载服务提供者:module-info.javaMETA-INF/services

  • ServiceLoader#load(Class,ClassLoader)

    • 在命名模块(即模块路径)和未命名模块(即类路径)中定位提供程序。

  • ServiceLoader#load(ModuleLayer,Class)

    • 仅在命名模块(即模块路径)中定位提供程序。


查看完整回答
反对 回复 2023-10-13
  • 1 回答
  • 0 关注
  • 158 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信