Что-то похожее на ServiceLoader в Java 1.5? - PullRequest
15 голосов
/ 30 октября 2008

Как мне обнаружить классы во время выполнения в classpath, который реализует определенный интерфейс?

ServiceLoader хорошо подходит (я думаю, я не использовал его), но мне нужно сделать это в Java 1.5.

Ответы [ 7 ]

19 голосов
/ 30 октября 2008

Нет ничего встроенного в Java 1.5 для этого. Я реализовал это сам; это не слишком сложно. Однако при обновлении до Java 6 мне придется заменить вызовы моей реализации вызовами на ServiceLoader. Я мог бы определить небольшой мост между приложением и загрузчиком, но я использую его только в нескольких местах, и сама обертка будет хорошим кандидатом для ServiceLoader.

Это основная идея:

public <S> Iterable<S> load(Class<S> ifc) throws Exception {
  ClassLoader ldr = Thread.currentThread().getContextClassLoader();
  Enumeration<URL> e = ldr.getResources("META-INF/services/" + ifc.getName());
  Collection<S> services = new ArrayList<S>();
  while (e.hasMoreElements()) {
    URL url = e.nextElement();
    InputStream is = url.openStream();
    try {
      BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
      while (true) {
        String line = r.readLine();
        if (line == null)
          break;
        int comment = line.indexOf('#');
        if (comment >= 0)
          line = line.substring(0, comment);
        String name = line.trim();
        if (name.length() == 0)
          continue;
        Class<?> clz = Class.forName(name, true, ldr);
        Class<? extends S> impl = clz.asSubclass(ifc);
        Constructor<? extends S> ctor = impl.getConstructor();
        S svc = ctor.newInstance();
        services.add(svc);
      }
    }
    finally {
      is.close();
    }
  }
  return services;
}

Лучшая обработка исключений оставлена ​​читателю в качестве упражнения. Кроме того, метод может быть параметризован для принятия ClassLoader по выбору вызывающей стороны.

6 голосов
/ 09 марта 2011

javax.imageio.spi.ServiceRegistry эквивалентно предыдущим версиям Java. Это доступно с Java 1.4.

Это не похоже на общий класс утилит, но это так. Он даже немного мощнее, чем ServiceLoader, так как позволяет контролировать порядок возвращаемых провайдеров и прямой доступ к реестру.

См. http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html

1 голос
/ 15 сентября 2011

Это старый вопрос, но другой вариант - использовать Примечания уровня пакета . Смотрите мой ответ для: Найти классы Java, реализующие интерфейс

Аннотации на уровне пакета - это аннотации в классах package-info.java.

JAXB использует это вместо Service Loaders. Я также думаю, что он более гибкий, чем сервисный загрузчик.

1 голос
/ 30 июня 2011

К сожалению,

Для этого нет ничего встроенного в Java 1.5 ...

это только часть правды.

Нестандартные sun.misc.Service вокруг.

http://www.docjar.com/docs/api/sun/misc/Service.html

Осторожно, он не является частью стандартного API J2SE! Это нестандартная часть Sun JDK. Таким образом, вы не можете положиться на это, если вы используете, скажем, JRockit.

1 голос
/ 31 октября 2008

ServiceLoader довольно прост и используется (неофициально) в JDK с 1.3. ServiceLoader, наконец, сделал его гражданином первого класса. Он просто ищет файл ресурсов с именем для вашего интерфейса, который в основном находится в каталоге META-INF библиотеки jar.

Этот файл содержит имя класса для загрузки.

Итак, у вас есть файл с именем:

META-INF / услуги / com.example.your.interface

и внутри него одна строка: com.you.your.interfaceImpl.

Вместо ServiceLoader мне нравится Netbeans Lookup. Работает с 1,5 (а может и с 1,4).

Из коробки он делает то же самое, что и ServiceLoader, и его тривиально использовать Но он предлагает гораздо больше гибкости.

Вот ссылка: http://openide.netbeans.org/lookup/

Вот статья о ServiceLoader, но там внизу упоминается Netbeans Lookup: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html

0 голосов
/ 04 декабря 2008

Думали ли вы об использовании каркаса OSGI?

0 голосов
/ 30 октября 2008

Нет надежного способа узнать, какие классы находятся в пути к классам. Согласно документации , ServiceLoader полагается на внешние файлы, чтобы сообщить, какие классы загружать; Вы можете сделать то же самое. Основная идея состоит в том, чтобы иметь файл с именем класса (ов) для загрузки, а затем использовать отражение для создания экземпляра его / их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...