java.util.ServiceLoader не загружает мой класс провайдера
Я пытаюсь собрать базовый реестр обработчиков на основе SPI, который я ищу из 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, который реализует этот интерфейс. Я создал файл в моем банке с именем META-INF/services/com.example.handler.Handler, который содержит одну строку
com.example.handler.handlers.DummyHandler
в соответствии с Javadoc. Мой модульный тест просто вызывает метод lookup() для проверки поиска обработчика для элемента. Конечно, в конечном итоге потребуется какая-то проверка, чтобы убедиться, что это правильный обработчик для этого элемента, но на данный момент я даже не вижу, как мой класс DummyHandler загружается реестром. Я что-то здесь не так делаю?
Спасибо!
1 ответ
Ответ, похоже, заключается в чувствительности к тому, как именно это настроено. Я поместил файл ресурса имени своего провайдера (файл с именем com.example.handler.Handler) непосредственно в каталог проекта верхнего уровня, т.е. /resources/META-INF/services/com.example.handler.Handler. Я настроил свой build.gradle, чтобы вытащить файл и положить его в банку:
jar { from('resources') { include 'META-INF/services/*.*' } }
Когда я проверил файл фляги, файл был там, где я и ожидал, поэтому я подумал, что все в порядке. При удачном стечении обстоятельств я случайно переместил папку ресурсов из папки src/main и presto! оно работает. Я проверил файл jar, и он кажется идентичным тому, который был создан предыдущим способом, но по какой-то причине этот работает. Я буду обновлять дальше, если смогу определить разницу, но, по крайней мере, мой тестовый пример работает сейчас.