使用Guice的模块化Java插件系统

时间:2016-05-17 14:31:03

标签: java dependency-injection guice

我们有一组接口,例如BookingInterface,InvoiceInterface,PaymentInterface,由不同的业务流程实现

e.g

Business1BookingInterface implements BookingInterface {
}
Business1InvoiceInterface implements InvoiceInterface {
} 
Business2BookingInterface implements BookingInterface {
}
Business2InvoiceInterface implements InvoiceInterface {
} 

我们正在考虑使每个业务流程成为实现暴露的接口集的插件。

在我们的rest API中,我们希望将一个特定的插件接口注入到我们的服务中

例如

 @Inject
public BillingService(Configuration configuration,
                      EventDispatcher eventDispatcher,
                      Map<String,PluginInterface> theCorrectInterfaceImplementation) {

}

我正在查找MapBindings,AssistedInjection和FactoryModuleBuilder,但不确定如何获得正确的Guice设置以在运行时注入所需的插件接口。

1 个答案:

答案 0 :(得分:2)

MapBinder(作为Multibindings功能之一)是对插件式界面的正确调用。 FactoryModuleBuilder是Assisted Injection的一个实现细节,它只是一种将显式构造函数参数与Guice提供的构造函数参数混合的方法。如果您不需要这样做,那么您不需要辅助注射。

您仍然需要在模块中设置这些绑定:

public Business1Module extends AbstractModule {
  @Override public void configure() {
    MapBinder<String, BookingInterface> bookingBinder =
        MapBinder.newMapBinder(binder(), String.class, BookingInterface.class);
    bookingBinder.addBinding("business1").to(Business1BookingInterface.class);
    MapBinder<String, InvoiceInterface> invoiceBinder =
        MapBinder.newMapBinder(binder(), String.class, InvoiceInterface.class);
    invoiceBinder.addBinding("business1").to(Business1InvoiceInterface.class);
  }
}

...然后在您的注射器中安装该模块。

Injector yourInjector = Guice.createInjector(/*...*/,
    new Business1Module(), new Business2Module());

结果是您不需要自己聚合这些依赖项,并且Guice不会抱怨与Map<String, BookingInterface>Map<String, InvoiceInterface>(等)的多个冲突绑定...它们将是自动合并为一个大地图。

其他说明:

  1. Multibindings位于单独的JAR中,因此不要忘记在类路径上安装它。

  2. 这可能是使用Modules with constructor parameters的绝佳理由:

    Injector yourInjector = Guice.createInjector(/*...*/,
    new BusinessModule("business1",
        Business1BookingInterface.class, Business1InvoiceInterface.class),
    new BusinessModule("business2",
        Business2BookingInterface.class, Business2InvoiceInterface.class));