gpt4 book ai didi

java - ServiceLoader 真的动态加载提供者吗?

转载 作者:搜寻专家 更新时间:2023-11-01 02:36:29 28 4
gpt4 key购买 nike

我最近发现关于服务加载器是否会在启动后定位添加到模块路径的提供程序的相互矛盾的文档。

ServiceLoader::reload :

public void reload​()

Clear this loader's provider cache so that all providers will be reloaded. After invoking this method, subsequent invocations of the iterator or stream methods will lazily locate providers (and instantiate in the case of iterator) from scratch, just as is done by a newly-created service loader.

This method is intended for use in situations in which new service providers can be installed into a running Java virtual machine.

这清楚地表明服务解析是完全动态的。

从另一方面ModuleFinder::findAll与它相矛盾。
“ModuleFinder 用于在解析或服务绑定(bind)期间查找模块。”Javadoc

Set<ModuleReference> findAll​()

Returns the set of all module references that this finder can locate. A ModuleFinder provides a consistent view of the modules that it locates. If findAll is invoked several times then it will return the same (equals) result each time. For each ModuleReference element in the returned set then it is guaranteed that find will locate the ModuleReference if invoked to find that module.

根据这个引用,解决方案固定在模块层创建上,这实际上是预期的,因为整个 Java 平台模块系统在设计上是静态的。如果新提供者需要其他模块,则必须修改现有模块图。

所以我的问题是:第一个引用是来自 Java 8 Javadoc 的遗留文档吗? ,或者在某些情况下我可以动态添加新的提供者?


在这里我要证明模块查找器文档是正确的:

com.service.Service:

package com.service;

import java.util.ServiceLoader;
import java.util.stream.Collectors;

public interface Service {

public static void main(String[] args) throws InterruptedException {
ServiceLoader<Service> loader = ServiceLoader.load(Service.class);

for (int i = 0; i < 5; i++) {
System.out.print("Attempt " + (i + 1) + ": ");
System.out.println(loader
.stream()
.map(ServiceLoader.Provider::type)
.map(Object::toString)
.collect(Collectors.joining(", ")));

Thread.sleep(5000);
loader.reload();
}
}
}

模块信息:

module service {
exports com.service;
uses com.service.Service;
}

在不同的模块中,class com.provider.Provider:

package com.provider;

import com.service.Service;

public class Provider implements Service {

}

模块信息:

module provider {
exports com.provider;
requires service;
provides com.service.Service with com.provider.Provider;
}

这是一个实时 GIF,当我第一次在模块路径中没有提供者的情况下运行它时会发生什么。在第二次运行时,提供程序已经存在,我将尝试在运行时将其删除。

console

最佳答案

服务提供者 API 在 Java 类加载器之上工作,默认情况下它们不是动态的。类路径在 JVM 启动时确定,然后不会更新:您要删除的 JAR 由 JVM 打开,直到关闭才会释放。如果您需要一些不同的行为,则需要使用自定义类加载器,例如 JEE 应用程序服务器用于部署 Web 应用程序的类加载器或 OSGi 实现中的类加载器。

关于java - ServiceLoader 真的动态加载提供者吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49353106/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com