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
What is the best way to inject a list with google-guice?
提问by Name is carl
I have three classes CircleBuilder
, SquareBuilder
, and TriangleBuilder
implementing the ShapeBuilder
interface.
我有三个类CircleBuilder
, SquareBuilder
, 和TriangleBuilder
实现ShapeBuilder
接口。
I need to initialize my FormBuilder
and 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 FormBuilder
manually which defeats the purpose of using guice (because FormBuilder
is 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 @Provides
methodcan take in parameters (e.g. CircleBuilder
or 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 @Provides
method.
或者,您的@Provides
方法可以接受参数(例如CircleBuilder
或Provider<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);
}
}