我正在尝试整理一个基于SPI的基本处理程序注册表,该注册表是从HandlerRegistry查找的.当我使用ServiceLoader.load(Handler.class)初始化提供程序,然后迭代列表以延迟加载它们时,我没有看到该类的任何实例.为了使这一过程尽可能简单,我的HandlerRegistry类是:
public class HandlerRegistry
{
private static HandlerRegistry registry;
private ServiceLoader handlerLoader;
private HandlerRegistry()
{
handlerLoader = ServiceLoader.load(Handler.class);
}
public static synchronized HandlerRegistry getRegistry()
{
if (registry == null) {
registry = new HandlerRegistry();
registry.init();
}
return registry;
}
private void init()
{
System.out.println("HandlerRegistry.init()");
}
public Handler lookup(String item)
{
System.out.println("lookup("+item+")");
try {
Iterator it = handlerLoader.iterator();
while (it.hasNext()) {
Handler handler = it.next();
System.out.println("found handler "+handler);
}
}
catch (ServiceConfigurationError err) {
err.printStackTrace();
}
return null;
}
}
我有一个com.example.handler.Handler接口(为简单起见,现在为空),以及一个实现该接口的com.example.handler.handlers.DummyHandler类.我在jar中创建了一个名为META-INF / services / com.example.handler.Handler的文件,其中包含单行
com.example.handler.handlers.DummyHandler
根据javadoc.我的单元测试只是调用lookup()方法来验证查找项目的处理程序.当然,最终将需要进行某种检查,以查看这是否是该项目的正确处理程序,但是在这一点上,我什至没有看到注册表中加载了我的DummyHandler类.我在这里做错什么了吗?
谢谢!
解决方法:
答案似乎是对配置方式的敏感性.我一直将我的提供程序名称资源文件(一个名为com.example.handler.Handler)直接放置在顶层项目目录中,即/resources/META-INF/services/com.example.handler.Handler.我已经配置了build.gradle以将文件拉出并放入jar中:
jar { from('resources') { include 'META-INF/services/*.*' } }
当我检查jar文件时,文件就在我期望的位置,所以我认为一切都很好.踢了一下,我碰巧将资源文件夹从src / main下移到了presto!有用.我检查了jar文件,它看起来与以前的方法相同,但是由于某种原因,它可以工作.如果可以确定差异,我将进行进一步更新,但是至少我的测试用例现在可以正常工作.
标签:serviceloader,java
来源: https://codeday.me/bug/20191122/2063668.html