我该怎么处理Guice,当我需要调用一个也可以注入的父构造函数?例如:我有一个抽象的父类,它有一个构造函数,该构造函数被注入了一个所有派生子类共享的对象,并且每个子类也都有可注入的构造函数。
调用super()将不起作用,因为Java希望我将对象作为参数传递而不是让Guice注入。
谢谢
编辑:我想知道是否需要使用方法注入?
如果你不使用Guice,你需要做完全相同的事情...在每个子类的构造函数中声明任何父类构造函数所需的参数作为参数,并将它们传递给super
。
因此,如果你的抽象父类构造函数需要一个Foo
,那么一个子类的构造函数应该像这样:
@Inject public ChildClass(Foo foo, Bar bar) {
super(foo);
this.bar = bar;
...
}
super()
。这使得构造函数注入变得麻烦,特别是在注入的基类发生更改时。public class TestInheritanceBinding {
static class Book {
final String title;
@Inject Book(@Named("GeneralTitle") String title) {
this.title = title;
}
}
static class ChildrensBook extends Book {
@Inject ChildrensBook(@Named("ChildrensTitle") String title) {
super(title);
}
}
static class ScienceBook extends Book {
@Inject ScienceBook(@Named("ScienceTitle") String title) {
super(title);
}
}
@Test
public void bindingWorked() {
Injector injector = Guice.createInjector(new AbstractModule() {
@Override protected void configure() {
bind(String.class).
annotatedWith(Names.named("GeneralTitle")).
toInstance("To Kill a Mockingbird");
bind(String.class).
annotatedWith(Names.named("ChildrensTitle")).
toInstance("Alice in Wonderland");
bind(String.class).
annotatedWith(Names.named("ScienceTitle")).
toInstance("On the Origin of Species");
}
});
Book generalBook = injector.getInstance(Book.class);
assertEquals("To Kill a Mockingbird", generalBook.title);
ChildrensBook childrensBook = injector.getInstance(ChildrensBook.class);
assertEquals("Alice in Wonderland", childrensBook.title);
ScienceBook scienceBook = injector.getInstance(ScienceBook.class);
assertEquals("On the Origin of Species", scienceBook.title);
}
}
public abstract class Animal {
/**
* All injectable fields of the Animal class, collected together
* for convenience.
*/
protected static final class AnimalFields {
@Inject private Foo foo;
@Inject private Bar bar;
}
private final AnimalFields fields;
/** Protected constructor, invoked by subclasses. */
protected Animal(AnimalFields fields) {
this.fields = fields;
}
public Foo getFoo() {
// Within Animal, we just use fields of the AnimalFields class directly
// rather than having those fields as local fields of Animal.
return fields.foo;
}
public Bar getBar() {
return fields.bar;
}
}
public final class Cat extends Animal {
private final Whiskers whiskers;
// Cat's constructor needs to inject AnimalFields to pass to its superclass,
// but it can also inject whatever additional things it needs.
@Inject
Cat(AnimalFields fields, Whiskers whiskers) {
super(fields);
this.whiskers = whiskers;
}
...
}