Как должен работать API Java Service Provide? - PullRequest
5 голосов
/ 21 декабря 2010

Кажется, что у всех была неприятная кисть с провайдером услуг Java , которую вы можете сделать с файлом с именем, например META-INF / services / com.example.Interface, но никто не использует за исключением попытки загрузить правильный анализатор XML. Я пытаюсь работать с библиотекой, использующей API Service Provider, и обманываю ее, чтобы я мог предоставить некоторые расширенные во время выполнения классы (используя cglib), которые на самом деле не реализуют интерфейс, но могут быть легко сделаны.

В принципе, я думаю, что мне нужно выполнить следующие шаги:

  1. Создайте пользовательский загрузчик классов, который будет отвечать на getResources (...) и возвращать «дополнительный» URL
  2. Иметь этот загрузчик классов getResourceAsStream (...), чтобы возвращать список классов, которыми я собираюсь манипулировать с помощью cglib, когда запрашивается «дополнительный» ресурс
  3. Наконец, загрузчик классов загружает эти классы по запросу

Но вот где я заблудился. Например, когда библиотека пытается определить, какие реализации существуют, она вызывает метод getResources (...), который возвращает несколько URL-адресов. Но getResourceAsStream (...) не берет URL-адреса, он принимает «имена». Имена, которые кажутся относительными к классам и, следовательно, везде одинаковы. Таким образом, META-INF / services / com.example.Interface in имеет то же «имя», что и META-INF / services / com.example.Interface в их JAR, верно? Кроме как-то это работает с этими взорванными парсерами XML ...

Конечно, все это предполагает, что они достаточно умны / добры, чтобы вызывать ClassLoader.getSystemClassLoader (), а не использовать ClassLoader.getSystemResources (...), ClassLoader.getSystemResourceAsStream (...) и т. Д., Как в В последнем случае нет способа перехватить ClassLoader и предоставить поддельный файл.

Полагаю, в этом случае я мог бы использовать BCEL для манипулирования файлами классов, когда мой код упакован в Maven, вместо ожидания времени выполнения, чтобы сделать это с помощью cglib?

1 Ответ

3 голосов
/ 27 декабря 2010

Идея, которую я описал, шла по правильному пути. Ошибка, которую я сделал, заключалась в том, что я использовал ClassLoader.getResourceAsStream(..) для доступа к содержимому URL. Вместо этого вы должны просто URL.openStream().

Если бы я нашел его до публикации, java.util.ServiceLoader (@since 1.6) дает некоторое представление о том, как правильно делать вещи.

...