Простые Java "платформы провайдеров услуг"? - PullRequest
5 голосов
/ 17 июля 2009

Я имею в виду «инфраструктуру поставщика услуг», как обсуждалось в главе 2 «Эффективной Java» , которая кажется совершенно правильным способом решения возникающей у меня проблемы, когда мне нужно создать экземпляр одного из нескольких классов во время выполнения на основе String для выбора какой службы и объекта Configuration (по сути, фрагмента XML):

Но как мне заставить отдельных провайдеров услуг (например, группу провайдеров по умолчанию + некоторых нестандартных провайдеров) зарегистрироваться самостоятельно?

 interface FooAlgorithm
 {
     /* methods particular to this class of algorithms */
 }

 interface FooAlgorithmProvider
 {
     public FooAlgorithm getAlgorithm(Configuration c);
 }

 class FooAlgorithmRegistry
 {
     private FooAlgorithmRegistry() {}
     static private final Map<String, FooAlgorithmProvider> directory =
        new HashMap<String, FooAlgorithmProvider>();
     static public FooAlgorithmProvider getProvider(String name)
     {
         return directory.get(serviceName);
     }
     static public boolean registerProvider(String name, 
         FooAlgorithmProvider provider)
     {
         if (directory.containsKey(name))
            return false;
         directory.put(name, provider);
         return true;
     }
 }

например. если я напишу пользовательские классы MyFooAlgorithm и MyFooAlgorithmProvider для реализации FooAlgorithm, и я распространю их в банке, есть ли способ получить автоматический вызов registerProvider, или мои клиентские программы, использующие алгоритм, должны явно вызывать FooAlgorithmRegistry.registerProvider () для каждого класса, который они хотят использовать?

Ответы [ 2 ]

10 голосов
/ 17 июля 2009

Я думаю, что вам нужно создать META-INF / services / полностью.qualified.ClassName и перечислить вещи там, но я не помню спецификации ( JAR File Specification или this ).

Практическое признание API 1007 * в архитектуре Java Книга, глава 8, посвящена SPI.

ServiceLoader может помочь вам перечислить доступные реализации. Например, с интерфейсом PersistenceProvider:

ServiceLoader<PersistenceProvider> loader = 
        ServiceLoader.load(PersistenceProvider.class);
Iterator<PersistenceProvider> implementations = loader.iterator();
while(implementations.hasNext()) {
    PersistenceProvider implementation = implementations.next();
    logger.info("PersistenceProvider implementation: " + implementation);
}
1 голос
/ 17 июля 2009

Вы можете сделать так, чтобы клиентский JAR регистрировал поставщиков в статическом блоке инициализатора в некотором классе, который, как вы знаете, будет вызываться до FooAlgorithmRegistry.getProvider(), что-то вроде:

static {
    FooAlgorithmRegistry.registerProvider("test", new MyFooAlgorithmProvider());
}

Но может быть довольно сложно найти способ гарантировать, что это будет работать (статические инициализаторы гарантированно будут запускаться один раз и только один раз, когда класс загружается впервые) до метода доступа фабрики.

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