我正在尝试组建一个基于SPI的基本的Handlers注册表,我从HandlerRegistry查找。当我使用ServiceLoader.load(Handler.class)初始化提供程序,然后迭代列表以延迟加载它们时,我没有看到该类的任何实例。保持这个尽可能简单,我的HandlerRegistry类是:
public class HandlerRegistry
{
private static HandlerRegistry registry;
private ServiceLoader<Handler> 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<Handler> 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类被注册表加载。我在这里做错了吗?
谢谢!
答案 0 :(得分:3)
答案似乎在于对这个配置的准确性的敏感性。我一直将我的提供者名称资源文件(名为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文件,看起来与之前构建的文件相同,但出于某种原因,这个工作正常。如果我可以确定差异,我会进一步更新,但至少我的测试用例现在可以使用。