java 使用 google-guice 注入列表的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14203696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:27:31  来源:igfitidea点击:

What is the best way to inject a list with google-guice?

javadependency-injectionguice

提问by Name is carl

I have three classes CircleBuilder, SquareBuilder, and TriangleBuilderimplementing the ShapeBuilderinterface.

我有三个类CircleBuilder, SquareBuilder, 和TriangleBuilder实现ShapeBuilder接口。

I need to initialize my FormBuilderand notably a BuilderList(extending List<ShapeBuilder>) with one instance of each class with google-guice.

我需要用 google-guice 用每个类的一个实例初始化我的FormBuilder,尤其是一个BuilderList(扩展List<ShapeBuilder>)。

What is the best way?

什么是最好的方法?

I know about the provider methods and stuff like this:

我知道提供者方法和这样的东西:

@Provides
FormBuilder provideFormBuilder() {
    DatabaseTransactionLog instance = new FormBuilder ( <numerous parameters> );

    ShapeBuilder builder = null ; 
    builder = new CircleBuilder( <numerous parameters> ) ;  
    instance.addBuilder( builder ) ;

    builder = new SquareBuilder( <numerous parameters> ) ;  
    instance.addBuilder( builder ) ;

    // And so on

    return instance;
}

but it would mean that I have to create my FormBuildermanually which defeats the purpose of using guice (because FormBuilderis the top element in my object graph).

但这意味着我必须FormBuilder手动创建,这违背了使用 guice 的目的(因为FormBuilder是对象图中的顶部元素)。

I'd love to be able to write something like this:

我希望能够写出这样的东西:

bind(BuilderList.class).to(CircleBuilder.class);
bind(BuilderList.class).to(TriangleBuilder.class);
bind(BuilderList.class).to(SquareBuilder.class);

Any idea?

任何的想法?

回答by Jeff Bowman

Consider Multibindings, which will collect bindings very much like your code snippet. There is no provision for lists through Multibinder, because Multibinder is designed for binding to the same collection in multiple modules, and the element order of a Multibinder list would depend on the order that your Modules were evaluated.

考虑Multibindings,它会像您的代码片段一样收集绑定。没有通过 Multibinder 提供列表,因为 Multibinder 旨在绑定到多个模块中的同一个集合,并且 Multibinder 列表的元素顺序将取决于您的模块被评估的顺序。

Multibinder<ShapeBuilder> shapeBinder =
    Multibinder.newSetBinder(binder(), ShapeBuilder.class);
shapeBinder.addBinding().to(CircleBuilder.class);
shapeBinder.addBinding().to(TriangleBuilder.class);
shapeBinder.addBinding().to(SquareBuilder.class);

// Now you can inject Set<ShapeBuilder>.

Alternatively, your @Providesmethodcan take in parameters (e.g. CircleBuilderor Provider<CircleBuilder>) so you can have Guice create everything except the List itself. Not only will Guice bind Providers of all bound types automatically, but it will also inject every parameter in any @Providesmethod.

或者,您的@Provides方法可以接受参数(例如CircleBuilderProvider<CircleBuilder>),因此您可以让 Guice 创建除 List 本身之外的所有内容。Guice 不仅会自动绑定所有绑定类型的提供者,而且还会在任何@Provides方法中注入每个参数。

@Provides List<ShapeBuilder> provideShapeBuilders(
    CircleBuilder circleBuilder,
    SquareBuilder squareBuilder,
    TriangleBuilder triangleBuilder,
    Provider<TrapezoidBuilder> trapezoidBuilderProvider) {
  return new ArrayList<ShapeBuilder>(
      circleBuilder,
      squareBuilder,
      triangleBuilder,
      trapezoidBuilderProvider.get(),
      trapezoidBuilderProvider.get());
}

回答by Kartik Goyal

We can do something like this:-

我们可以这样做:-

@Override
protected void configure() {
    bind(ShapeBuilder.class).annotatedWith(Names.named("Circle")).to(CircleBuilder.class);
    bind(ShapeBuilder.class).annotatedWith(Names.named("Triangle")).to(TriangleBuilder.class);
    bind(ShapeBuilder.class).annotatedWith(Names.named("Square")).to(SquareBuilder.class);
}

In your FormBuilder Class:-

在您的 FormBuilder 类中:-

class FormBuilder{
   List<ShapeBuilder> shapeBuilderList;
   @Inject
   public FormBuilder(@Named("Circle")ShapeBuilder circle, @Named("Triangle")ShapeBuilder triangle,@Named("Square")ShapeBuilder square){
       shapeBuilderList = new ArrayList<>();
       //add all of them
       shapeBuilderList.add(circle);
    }
}