繁体   English   中英

ServiceLoader是否真的动态加载提供程序?

[英]Does ServiceLoader really load providers dynamically?

我最近发现了矛盾的文档,服务加载器是否会在引导后将提供程序添加到模块路径中。

ServiceLoader::reload

 public void reload​() 

清除此加载程序的提供程序缓存,以便重新加载所有提供程序。 在调用此方法之后,迭代器或流方法的后续调用将从头开始懒惰地定位提供程序(并在迭代器的情况下实例化),就像新创建的服务加载器一样。

此方法适用于可以将新服务提供程序安装到正在运行的Java虚拟机中的情况。

这清楚地表明服务分辨率是完全动态的。

另一方面, ModuleFinder::findAll与之相矛盾。
“ModuleFinder用于在解析或服务绑定期间查找模块。” - Javadoc

 Set<ModuleReference> findAll​() 

返回此finder可以找到的所有模块引用的集合。 ModuleFinder提供了它所找到的模块的一致视图。 如果多次调用findAll,那么每次都会返回相同的(等于)结果。 对于返回集合中的每个ModuleReference元素,保证find会在调用时找到ModuleReference以查找该模块。

根据这个引用,解决方案在模块层创建时得到了修复,实际上这是因为整个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-info

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

在另一个模块中,类com.provider.Provider

package com.provider;

import com.service.Service;

public class Provider implements Service {

}

module-info

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

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

安慰

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM