Что-то похожее на ServiceLoader в Java 1.5?

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

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

7 ответов

Решение

Для этого нет ничего встроенного в 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 по выбору вызывающей стороны.

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

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

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

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

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

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

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

К несчастью,

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

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

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

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

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

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

Вы думали об использовании OSGI Framework?

Другие вопросы по тегам