Связывание на основе пользовательских аннотаций - PullRequest
2 голосов
/ 16 июля 2011

Я новичок как в стеке потока, так и в guice.Я не уверен, что то, что я пытаюсь сделать, возможно с хитростью, но я надеюсь, что это так.

Моя проблемная область в том, что я пытаюсь написать систему чтения документов.Я определил интерфейс для DocumentReader.

public interface DocumentReader {
    MetaData readDocument() throws Exception
}

Я также определил перечисление, определяющее поддерживаемые типы файлов (т.е. расширения).

public enum FileType {
    doc,
    png,
    txt,
}

У меня есть реализация для каждого FileType,предоставляя подробную информацию о том, как анализировать этот тип файла.

public class MSWordReaderImpl implements DocumentReader {
    // ....
}

public class PlainTextReaderImpl implements DocumentReader {
    // ....
}

На данный момент я успешно написал и протестировал модуль, который использует MapBinder & FactoryModuleProvider для внедрения каждого из этих объектов.Каждая существующая реализация DocumentReader добавляется в MapBinder по отдельности.Я надеюсь, что по мере написания дополнительных реализаций DocumentReader я мог бы просто аннотировать их, с помощью которых FileType (ы), которые они поддерживают, и GUICE мог бы читать аннотации и добавлять их в MapBinder соответствующим образом (без необходимостиобновить модуль за добавление).Я представлял себе что-то вроде этого:

@SupportedFileTypes( filetypes={ doc, docx } )
public class MSWordReaderImpl implements DocumentReader {
    // ....
}

@SupportedFileTypes( filetypes={txt} )
public class PlainTextReaderImpl implements DocumentReader {
    // ....
}

Я прочитал документацию GUICE несколько раз, но я просто не вижу способа сделать это (если это вообще возможно!),Любая помощь будет оценена.

Спасибо!

Ответы [ 2 ]

1 голос
/ 16 июля 2011

Ваш модуль может сканировать пакеты, в которые будут добавлены классы, используя отражение, ища классы, которые реализуют DocumentReader и помечены @SupportedFileTypes.Когда он найдет его, добавьте его в MapBinder для каждого типа файла.

Если вы не хотите сканировать путь к классам, вы все равно можете упростить это для себя, написав такой метод:*

private void bindDocumentReaders(Class<? extends DocumentReader>... types) {
  for (Class<? extends DocumentReader> type : types) {
    FileType[] supportedFileTypes = type.getAnnotation(SupportedFileTypes.class)
        .filetypes();
    // add to MapBinder for each file type
  }
}
1 голос
/ 16 июля 2011

Самый простой способ увидеть, как это работает, - посмотреть на источник для класса Именованные и Имена , и как он используется .

Сначала создайте аннотацию RequiredFileType,

@Retention(RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@BindingAnnotation
public @interface RequiredFileType {
  FileType value();
}

Затем аннотируйте класс, который зависит от читателя документа, например,

@Inject
ServiceRequiringWordReader(@RequiredFileType(doc) DocumentReader reader)

Затем создайте утилиту RequiredFileTypes, которая эквивалентна Именам (код пропущен), и в своем модуле напишите код, подобный,

bind(DocumentReader.class)
    .annotatedWith(RequiredFileTypes.for(doc))
    .to(MSWordReaderImpl.class);
bind(DocumentReader.class)
    .annotatedWith(RequiredFileTypes.for(docx))
    .to(MSWordReaderImpl.class);
bind(DocumentReader.class)
    .annotatedWith(RequiredFileTypes.for(txt))
    .to(PlainTextReaderImpl.class);
...