2011-07-16 178 views
2

我對stackoverflow和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 { 
    // .... 
} 

我已經通過吉斯文檔多次閱讀,但我只是沒有看到一個方法來做到這一點(如果它甚至有可能!)。任何幫助,將不勝感激。

謝謝!

回答

1

你可以讓你的模塊掃描包中的類將使用反射,尋找類實現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 
    } 
} 
+0

這是我一直在考慮的解決方案。我只是不確定它是否是GUICE開箱即用的東西。根據我在文檔中讀到的內容,GUICE模塊旨在輕量級(甚至不會讓您拋出異常)。掃描類路徑對我來說似乎不重要,但也許我的選擇是有限的。 – scubadev

+0

@ Zildijan85:Guice模塊可以像你想的那樣真正輕量級或者不是。通常他們只是簡單的綁定而且非常輕便,但在某些情況下,您可能希望他們讀取文件或其他任何文件。儘管Guice不提供任何對類路徑掃描的支持,但它通常更喜歡讓事情更加明確。 – ColinD

+0

我相信這種方法適用於我的目的。我的動機是創建一個插件系統,使第三方能夠編寫自定義閱讀器。我喜歡它,以便第三方只需要實現DocumentReader並使用@SupportedFileTypes({x,y,z})對其實現進行註釋。我傾向於將類似於您的解決方案的東西放到DocumentReaderDiscovertyService中。 DocumentReader GUICE模塊將調用該服務來查找所有實現。發現服務可以使用配置或其他機制來允許第三方識別他們的工作。 – scubadev

1

查看工作原理的最簡單方法是查看NamedNames類的來源,以及它如何成爲used

首先創建一個RequiredFileType註釋,

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

然後註釋取決於文件讀取器等類,

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

然後創建一個RequiredFileTypes工具,它是等效於名稱(代碼ommitted),並在你的模塊寫代碼,如

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); 
+0

我將不得不看看命名及名稱公用事業看如果他們有任何寶石。你的回答很有幫助,但我不確定它滿足了我在找什麼。 ServiceRequiringWordReader要求您瞭解構造函數中所有支持的文件類型。我想爲MSWordReaderImpl註釋它所支持的文件類型,並且這是文件類型唯一關聯的地方。我認爲在您的解決方案中,每次創建新實現時都必須更新ServiceRequiringWordReader。 – scubadev