问题标签 [serviceloader]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - ServiceLoader、URLClassLoader 和 Spring:java.lang.NoClassDefFoundError
我正在尝试加载一个外部 module.jar,它从我的主 spring 应用程序中实现了一个接口。
因此我实施了这个解决方案
不幸的是,这引发了这个异常:
我应该在我的模块中将我的主应用程序声明为依赖项吗?目前我的模块只有自己的依赖项。
我在网上找到的资源对这个问题并不是很清楚。
java - Java ServiceLoader 解释
我试图了解 JavaServiceLoader
概念、工作机制和具体用例,但发现官方文档过于抽象和混乱。
首先,文档概述了服务和服务提供者。服务是封装在 jar 档案(API 库)中的一组接口和抽象类。服务提供者是一组实现或扩展 API 的类,打包在一个不同的 jar 文件(提供者库)中。
到目前为止一切都很好,但是文档变得混乱。
出于加载的目的,服务由单一类型表示,即单一接口或抽象类。(可以使用具体类,但不推荐这样做。)给定服务的提供者包含一个或多个具体类,这些具体类使用提供者特定的数据和代码扩展此服务类型。提供者类通常不是整个提供者本身,而是一个代理,它包含足够的信息来决定提供者是否能够满足特定请求以及可以按需创建实际提供者的代码。提供者类的细节往往是高度特定于服务的;没有一个类或接口可以统一它们,所以这里没有定义这样的类型。
那么实际上服务类型和提供者类是什么?我的印象是,服务类型是API库中的一个门面,而提供者类是提供者库中这个门面接口的实现,是ServiceLoader
实际加载的类。这个对吗?但对我来说,所有组件如何联系在一起仍然没有多大意义。
提供者类作为代理来决定提供者是否能够满足特定请求以及可以按需创建实际提供者的代码是什么意思?不能在哪里定义统一类型?基本上这一段都是令人困惑的,我想通过一个具体的例子来听听更容易理解的解释。
然后关于提供者配置文件...
通过在资源目录 META-INF/services 中放置提供者配置文件来识别服务提供者。该文件的名称是服务类型的完全限定二进制名称。该文件包含具体提供程序类的完全限定二进制名称列表,每行一个...
命名特定提供者的配置文件不必与提供者本身位于相同的 jar 文件或其他分发单元中。必须可以从最初查询配置文件的同一个类加载器访问提供程序;请注意,这不一定是实际加载文件的类加载器。
这是否意味着对于服务类型为 org.foo.BarServiceType 的 API,在类路径中必须存在提供程序 jar,该提供程序 jar 具有实现此类型的类和 META-INF/services/org.foo.BarServiceType
列出此提供程序类的命名提供程序配置文件,所有这些都可以通过Classloader
加载ServiceLoader
找到的相同访问并在 API 上绑定提供者?
从类加载器的角度来看,可访问意味着提供程序配置文件和提供程序库可以在包之外提供,在层次结构的上层,即来自容器或其他中间件。
提供者配置文件列出了提供者类,并且可能捆绑在提供者包中(如果捆绑了,为什么它会列出多个类?)或者来自外部。但是哪种方法更常见:在提供者之间提供配置文件,还是提供列出 API 库本身中一组支持的提供者的文件?还是后者是一种误解?
最后关于ServiceLoader
在哪里ServiceLoader
实际实例化并调用以加载服务提供者?这是否发生在API 库提供的工厂方法中?例如,SLF4J 内部是否LoggingFactory.getLogger(clazz)
委托给,ServiceLoader
它使用反射来读取提供程序配置文件并加载服务?。
服务加载机制如何处理以下情况:有多个提供者及其配置文件存在,或者有提供者配置文件条目但没有类本身?
ServiceLoader
日志框架之外的其他一些具体用例是什么?它在Java EE、Spring和Hibernate等流行框架的底层使用了多少?具有松散耦合 API 的服务加载机制有哪些替代方案 - 提供者绑定,或者是否存在?
java - 如何将 ExchangeRateProvider 添加到 javax.money
我编写了一个需要依赖注入的自定义 ExchangeRateProvider。但是对于 java.money,您需要在META-INF/services/javax.money.convert.ExchangeRateProvider下的文件中添加自定义类。普通的 ServiceLoader 不使用依赖注入。
我使用spring,所以我的想法是使用spring上下文进行依赖管理,然后将其添加到java.money上下文中。
有谁知道如何做到这一点?
java - Java 安全管理器:对通过 ServiceLoader 加载的外部 jar 代码的限制
我想达到什么目的? 我正在开发一个可以通过通过 ServiceLoader 集成的其他 jar 扩展的 java 应用程序。这些加载的扩展应该在 SecurityManager 的一些限制下运行,当然只是为了提高安全性。例如,每个扩展都应获得一个可以存储任何内容的特定目录,但应限制对任何其他文件/文件夹的访问。主应用程序是受信任的代码,因此可以不受任何限制地运行。此外,主应用程序为每个扩展提供了一些 api 实现,这些扩展也应该不受限制地运行。这意味着扩展不能访问其目录之外的文件,但是当扩展调用试图访问任何其他文件的 api 方法时,应该授予访问权限。
问题 如何实现上述行为,即仅来自扩展类的“直接”调用受到限制,而主应用程序中的任何代码均不受限制?无论如何,在不同的线程/线程组中运行扩展可能是一个很好的解决方案,但由于对 api 的调用可能在同一个线程(组)下运行,因此可能无助于识别是否应该仅基于线程来限制访问。
示例 我创建了一个简化的测试环境。一方面有这两个接口:
为了测试,我创建了一个包含这个扩展的 jar:
在主应用程序中,我想做这样的事情:
因此,当我调用extension.doSomethingRestricted();
它时,它应该会导致 SecurityException,但调用extension.doSameViaApi(api);
应该可以正常工作。所以这两种方法都尝试做同样的事情,但一种方法确实尝试通过 api 调用来做。我能想到的唯一方法是遍历调用历史并检查类加载器以分析访问请求是基于可信代码还是基于扩展代码。但我觉得这可能是一个令人讨厌的容易出错的解决方案,所以也许我错过了一些更好的方法?
java - 关于 serviceloader 的 Java 9 依赖问题
我对基于这种情况的 Java 9 中的服务加载器如何更改有疑问
设想
项目gert
类Main
项目gert
类ClassesDef
项目gert
pom.xml
项目cristina
类Main
项目cristina
pom.xml
于是cristinamain
加载了gert项目,执行了一个名为gert的方法test()
测试
Java 8
当项目使用 java 8 运行时,它可以工作
命令
"C:\Program Files\Java\jre1.8.0_151\bin\java.exe" -cp C:\Users\gert\eclipse-workspace91java\cristina\target\cristina-0.0.1-SNAPSHOT.jar cristina.Main
输出
Before gert.Main.test();.
After gert.Main.test();.
Java 9
当对 Java 9 进行同样的操作时,它不会
命令
"C:\Program Files\Java\jre-9.0.1\bin\java.exe" -cp C:\Users\gert\eclipse-workspace91java\cristina\target\cristina-0.0.1-SNAPSHOT.jar cristina.Main
输出
上面的 2 是直接从命令行完成的。
但是
当我取消注释项目中的依赖pom.xml
项cristina
并执行 maven 安装并从 eclipse 运行项目时,java 9 可以工作。所以看起来eclipse在运行项目时也考虑了maven依赖。
问题
当依赖项在gert
项目中并且仅由gert
项目使用时,为什么cristina
项目在使用 Java 9 运行时会引发异常?
java - 类加载器和服务加载器。使用哪个类加载器?
我正在编写一个可扩展的应用程序。
阅读有关ServiceLoader实用程序类的文档,我无法理解以下句子:
必须可以从最初查询配置文件的同一个类加载器访问提供程序;请注意,这不一定是实际加载文件的类加载器。
谁能给我解释一下这是什么意思?
我如何确定它用于定位配置文件的类加载器?
java - JUnit5 Platform Launcher API - 如果没有至少一个 TestEngine,则无法创建 Launcher
我正在尝试升级我们的自动化测试套件的测试能力以接受 JUnit5 测试,当遵循JUnit 平台启动器 API 说明时,我收到错误“如果没有至少一个 TestEngine 就无法创建启动器;考虑将引擎实现 JAR 添加到类路径” . 原因是以下无法找到任何实例TestEngine
:
Iterable<TestEngine> testEngines = ServiceLoader.load(TestEngine.class,ClassLoaderUtils.getDefaultClassLoader());
您对如何确保ServiceLoader
能够找到 的实例有任何建议TestEngine
吗?
我已经包含了org.junit.jupiter.engine
,其中包含JupiterTestEngine
哪些实现TestEngine
,作为必需的插件。我尝试在项目的 .classpath 中添加到 jupiter.engine jar 的直接路径。我已经尝试创建一个具有JupiterTestEngine
相同文件的实例并且它已成功创建,但TestEngine
服务加载器仍然没有找到。
编辑(回应 Somuras 的评论):
这是针对 Eclipse 的,您可以在此处查看代码库:http: //git.eclipse.org/c/platform/eclipse.platform.releng.git/tree/bundles/org.eclipse.test
我在 mainifest 中添加了以下内容:
将此添加到.classplath:
将 org.junit.jupiter.engine jar 添加到 lib 文件夹,然后将其添加到二进制构建中。(我正在寻求解决方案)
我正在尝试让教程代码在http://git.eclipse.org/c/platform/eclipse.platform.releng.git/tree/bundles/org.eclipse.test/src的编辑版本中工作/org/eclipse/test/EclipseTestRunner.java 删除了所有旧的junit代码。
java - 在 OSGi 中,ServiceLoader.load 找不到实现
我们一直在尝试让 SPI Fly 与openstack4j-core和其中一个 openstack4j 连接器 ( openstack4j-httpclient ) 一起工作。就是org.openstack4j.core.transport.HttpExecutorService
需要SPIFly编织。
一个怪癖:两个包都是从一个 zip 文件加载的,并在系统的其余部分启动并运行后启动。相同的 zip 文件提供了org.apache.aries.spifly.dynamic.bundle
.
这两个捆绑包确实使用了SPI Fly 标准指令集中的 OSGI-Spec 兼容模型。根据这些说明,我们真正需要的只是两个包的 MANIFEST.MF 中的相应标头,以及 META-INF/ 下的服务声明Require-Capability
(如下所示)。Provide-Capability
核心捆绑包有:
httpclient 有:
(为了可读性,重新格式化,当然)
此外, openstack4j-httpclient有一个名为META-INF/servicesorg.openstack4j.core.transport.HttpExecutorService
的文件,只有一行:
我们还添加了org.apache.aries.spifly.dynamic.bundle
提供serviceloader.processor
和serviceloader.registrar
功能的包。
然后在运行时,ServiceLoader 调用只是找不到HttpExecutorService
.
PS:搞乱bundle的启动顺序没有效果,在所有bundle启动前调用resolveBundles
也FrameworkWiring
没有用。
osgi - 在 OSGI/Eclipse 中使用 Log4j2.10 和 slf4j-api 1.8
我正在尝试在我的 Eclipse 项目中使用 Log4j2.10 和 slf4j-api 1.8 beta1。我无法让绑定工作,slf4j 抱怨:
它与使用 slf4j 1.8 不再支持的 StaticLoggerBinder 机制的 Log4j 2.9.1 和 slf4j-api 1.7.24 一起使用
我的 Eclipse 插件依赖于
问题是在 LoggerFactory (slf4j-api) 中 ServiceLoader.load(SLF4JServiceProvider.class) 调用返回任何空列表,因此 org.apache.logging.log4j.slf4j-impl 的 spi 文件未找到或未加载.
有什么我错过了这个工作吗?
提前致谢,
抢
java - 简单的 ServiceLoader - java.util.ServiceConfigurationError ... Provider ... 未找到
我正在尝试使用 ServiceLoader 运行示例应用程序。为此,我创建了两个 JAR:
META-INF/services/ok.service.NumberService
有单行:ok.service.impl.NumberServiceImpl
META-INF/MANIFEST.mf
有Main-Class: ok.main.App
条目
并ok.main.App
加载提供者ok.service.NumberService
包含实现ok.service.NumberService
当命令运行为:
或(同一目录中的两个 JAR)
未找到提供程序。
无法弄清楚提供程序类是如何找不到的。请帮忙!
提前致谢。