使用注释为 Google guice MapBinder 提供数据

在 Java 项目中,使用 Gradle 5.2 和 Google Guice 进行构建。


我使用MapBinder(http://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/multibindings/MapBinder.html):


MapBinder<String, Snack> mapbinder

         = MapBinder.newMapBinder(binder(), String.class, Snack.class);

     mapbinder.addBinding("twix").toInstance(new Twix());

     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);

     mapbinder.addBinding("skittles").to(Skittles.class);

这工作正常,但现在,我想要一个“插件架构”,所以避免导入所有 Snack 类,而是直接在类中声明它,例如:


@SnackImpl("Twix")

class Twix extends Snack {


}

如何?


慕哥9229398
浏览 75回答 1
1回答

素胚勾勒不出你

如果没有一些昂贵的类路径扫描,这将是不可能的:如果注入器没有对您的 Twix 类的任何引用,它就无法在不扫描类路径上的每个 JAR 的情况下将其绑定到 Map 中@SnackImpl-带注释的类。您可以尝试使用Guava 的 ClassPath,但如果您使用基于网络或自定义的类加载器,这可能根本无法处理。无论如何,我不会推荐它。一种替代方法是使用 Java 的内置ServiceLoader框架,该框架允许各个 JAR 列出给定服务(接口)的完全合格的实现。您甚至可以使用 Google 的 Auto 框架根据注释为您生成该服务文件。这需要列出实现,但您仍然需要将它们绑定到 MapBinder。幸运的是,MapBinder 不需要单个定义,并且会在模块构建期间自动合并多个 MapBinder 定义:支持从不同模块贡献映射绑定。例如,可以让 CandyModule 和 ChipsModule 都创建自己的 MapBinder,并各自为小吃地图提供绑定。注入该映射后,它将包含来自两个模块的条目。(来自MapBinder 文档)考虑到这一点,我建议每个插件包都有自己的 Guice 模块,并在其中注册到 MapBinder,然后使用 ServiceLoader 将这些 Guice 模块添加到主注入器,以便在注入器创建时获取这些模块。// Assume CandyPluginModule extends AbstractModule@AutoService(CandyPluginModule.class)public TwixPluginModule extends CandyPluginModule {&nbsp; @Override public void configure() {&nbsp; &nbsp; MapBinder<String, Snack> mapBinder&nbsp; &nbsp; &nbsp; &nbsp;= MapBinder.newMapBinder(binder(), String.class, Snack.class);&nbsp; &nbsp; mapBinder.addBinding("twix").to(Twix.class);&nbsp; }}您还可以利用超类:@AutoService(CandyPluginModule.class)public TwixPluginModule extends CandyPluginModule {&nbsp; @Override public void configureSnacks() {&nbsp; // defined on CandyPluginModule&nbsp; &nbsp; bindSnack("twix").to(Twix.class);&nbsp; }}或者,您可以直接使用 AutoService 列出 Twix 之类的实现,然后创建一个模块,将所有 ServiceLoader 实现读入您的 MapBinder,但这可能会限制您的插件的灵活性,并且不会让您获得 MapBinder 没有的绑定的任何分散化还没给你。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java