gpt4 book ai didi

java - 使用ServiceLoader实现JRE服务,但不带模块

转载 作者:行者123 更新时间:2023-12-02 10:22:24 25 4
gpt4 key购买 nike

我们在 Java 8 下有一个非常大的项目。我暂时需要使用 Java 9 中引入的功能1来调试问题,所以我的计划是构建并运行主要 -当前工具(可能是 11.0.1),添加最少的代码来调用该功能,然后根本不将任何调试更改合并到主干。

挑战在于我不想费力地构建 module-info.java仅仅为了这个。 (现有的非模块代码实际上在 Java SE 11 下构建和运行没有任何问题,只是生产用户环境仅限于 Java 8。因此,我们几乎没有付出任何努力来尝试模块化该项目。)

为什么模块可能很重要:我需要使用的功能是 System.LoggerFinder ,可通过 ServiceLoader 找到。时尚新使用方式ServiceLoader是通过模块声明,这就是当前服务加载器文档花费最多时间描述的内容。将文本文件放在 META-INF/services/ 下的旧方法仍然有效,并且我们已经成功使用此类服务​​和提供程序类,但当前设置不适用于 LoggerFinder .

我们尝试加载的临时类

package com.example.for.stackoverflow;

public class LoggerFinder extends System.LoggerFinder
{
public LoggerFinder()
{
System.err.println("behold, a LoggerFinder");
}


@Override
public System.Logger getLogger (String name, Module module)
{
org.slf4j.Logger real = ...existing function to fetch logging facade...
return new SystemLoggerWrapper (name, real);
}
}

class SystemLoggerWrapper implements System.Logger { ... }

这种包装器实现非常简单,并且已在其他地方发布。2但是,已发布的示例都使用 module-info.java获取ServiceLoader到 DTRT。

该项目的构建系统是使用 Ant 完成的,因此我们在 <jar> 下添加了行任务:

<service type="java.lang.System.LoggerFinder">
<provider classname="com.example.for.stackoverflow.LoggerFinder"/>
</service>

这是有效的,因为最终的 JAR 包含 META-INF/services/java.lang.System.LoggerFinder包含正确类名的文本文件。

但是,在运行时,提供的 LoggerFinder没有被使用。查看 -verbose:class 的输出很明显,默认值仍然有效。 ServiceLoader 没有抛出任何异常本身。运行时类路径已经拾取 JAR,其中 LoggerFinder实现已生效(它不是唯一的服务,其他 ServiceLoader 式的提供程序正在被发现)。

关于该主题的现有问题很少, herehere ,但他们也走模块化路线。

是否有某种方法可以了解 ServiceLoader 的内容是在做?如果没有modules-info.java,这只是徒劳的练习吗? ?

<小时/>

1 我正在尝试激活来自 sun.util.logging.PlatformLogger 的调试消息系统,该系统(至少从 Java 9 开始)将通过 System.Logger 工作,并且如果 - 根据其自己的文档 - a System.LoggerFinder 则被激活可以通过ServiceLoader找到。所有这些杂耍都是为了 PlatformLogger 目标。

2 例如,https://www.baeldung.com/java-9-logging-api第三节下

最佳答案

方式ServiceLoader加载类路径上的类没有改变1。它仍然通过在 META-INF/services 下搜索适当的提供程序配置文件来定位提供程序。 .

LoggerFinder 的文档说它搜索system class loader可见的提供者。正如您在评论中提到的,该提供商通过 -cp 包含在内这不应该是一个问题。

提供程序配置文件的名称必须是 SPI 的完全限定的二进制名称。来自 ServiceLoader 文档:

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.

二进制名称LoggerFinder ,由 Class.getName 返回,是java.lang.System$LoggerFinder 。基于此,提供程序配置文件的名称应该是:

META-INF/services/java.lang.System$LoggerFinder

我对 Ant 一点也不熟悉,但我猜你应该更改 type 的值使用完全限定的二进制名称。

<service type="java.lang.System$LoggerFinder">
<provider classname="com.example.for.stackoverflow.LoggerFinder"/>
</service>

注意:当我自己测试时,我最初无法让系统使用我的 LoggerFinder实现要么。当我将提供程序配置文件名更改为java.lang.System$LoggerFinder时(最终阅读文档后)然后它按预期工作。不幸的是,我没有可用的 Ant 来测试 <jar> 的解决方案。任务。

<小时/>

1。除非你使用ServiceLoader.load(ModuleLayer,Class)因为它会忽略未命名的模块(即类路径)。

关于java - 使用ServiceLoader实现JRE服务,但不带模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54246026/

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