使用 Java 类路径执行 Java 9+ 服务
Using Java classpath to execute Java 9+ Services
我创建了一个简单的 Java9 服务示例,其中包含一个服务接口和两个服务实现以及一个使用 ServiceLoader 的驱动程序。我能够使用模块路径成功执行该示例,但是当我尝试使用 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.
时没有输出
服务提供者的定位方式取决于服务提供者是在类路径上还是在模块路径上。 ServiceLoader
:
的文档中对此进行了描述
Deploying service providers as modules
A service provider that is developed in a module must be specified in a provides directive in the module declaration. The provides directive specifies both the service and the service provider; this helps to locate the provider when another module, with a uses directive for the service, obtains a service loader for the service. It is strongly recommended that the module does not export the package containing the service provider. There is no support for a module specifying, in a provides directive, a service provider in another module.
[...]
Deploying service providers on the class path
A service provider that is packaged as a JAR file for the class path is identified by placing a provider-configuration file in the resource directory META-INF/services
. The name of the provider-configuration file is the fully qualified binary name of the service. The provider-configuration file contains a list of fully qualified binary names of service providers, one per line.
[...]
基本上,如果您希望能够加载服务提供者,无论它是放在类路径还是模块路径上,您都需要在 module-info.java
中同时指定 provides
指令文件并在 META-INF/services
下添加适当的提供程序配置文件。您还必须确保使用正确的方法加载服务提供商:
ServiceLoader#load(Class,ClassLoader)
- 在命名模块(即模块路径)和未命名模块(即类路径)中定位提供程序。
ServiceLoader#load(ModuleLayer,Class)
- 仅在命名模块(即模块路径)中定位提供程序。
我创建了一个简单的 Java9 服务示例,其中包含一个服务接口和两个服务实现以及一个使用 ServiceLoader 的驱动程序。我能够使用模块路径成功执行该示例,但是当我尝试使用 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.
时没有输出服务提供者的定位方式取决于服务提供者是在类路径上还是在模块路径上。 ServiceLoader
:
Deploying service providers as modules
A service provider that is developed in a module must be specified in a provides directive in the module declaration. The provides directive specifies both the service and the service provider; this helps to locate the provider when another module, with a uses directive for the service, obtains a service loader for the service. It is strongly recommended that the module does not export the package containing the service provider. There is no support for a module specifying, in a provides directive, a service provider in another module.
[...]
Deploying service providers on the class path
A service provider that is packaged as a JAR file for the class path is identified by placing a provider-configuration file in the resource directory
META-INF/services
. The name of the provider-configuration file is the fully qualified binary name of the service. The provider-configuration file contains a list of fully qualified binary names of service providers, one per line.[...]
基本上,如果您希望能够加载服务提供者,无论它是放在类路径还是模块路径上,您都需要在 module-info.java
中同时指定 provides
指令文件并在 META-INF/services
下添加适当的提供程序配置文件。您还必须确保使用正确的方法加载服务提供商:
ServiceLoader#load(Class,ClassLoader)
- 在命名模块(即模块路径)和未命名模块(即类路径)中定位提供程序。
ServiceLoader#load(ModuleLayer,Class)
- 仅在命名模块(即模块路径)中定位提供程序。