Загрузка реализаций общих служб через java.util.ServiceLoader

На днях я наткнулся на некоторые неудобства, используя java.util.ServiceLoader и некоторые вопросы сформировался во мне.

Предположим, у меня есть общий сервис:

public interface Service<T> { ... }

Я не мог явно указать ServiceLoader загружать только реализации с определенным универсальным типом.

ServiceLoader<Service<String>> services = 
   ServiceLoader.load(Service.class); // Fail.

Мой вопрос: каковы разумные способы использования ServiceLoader для безопасной загрузки реализаций универсального сервиса?


Задав вышеупомянутый вопрос и до ответа Паоло, мне удалось придумать решение.

public interface Service<T> { ...
    // true if an implementation can handle the given `t' type; false otherwise.
    public boolean canHandle(Class<?> t) { ...

public final class StringService implements Service<String> { ...
    @Override public boolean canHandle(Class<?> t) {
        if (String.class.isAssignableFrom(type)) 
            return true;
        return false;
    }

public final class DoubleService implements Service<Double> { ...
    // ...

public final class Services { ...
    public static <T> Service<T> getService(Class<?> t) {
        for (Service<T> s : ServiceLoader.load(Service.class))
            if (s.canServe(t))
                return s;
        throw new UnsupportedOperationException("No servings today my son!");
    }

Изменение логического canServe (Class T) на логическое canServe (Object o) , а также изменение Service getService (Class t) таким же образом может быть более динамичным (я использую последний для себя, поскольку вначале у меня был метод boolean canHandle (T t) в моем интерфейсе.)

8
задан Kohányi Róbert 26 November 2011 в 15:42
поделиться