2011-07-16 151 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