Guice AssistedInject не будет вводить фабрику
Я пытаюсь использовать Guice 3.0 AssistedInject
и это не будет создавать экземпляр фабрики.
Код SSCCE:
Родительский класс
public class ParentClass() {
@Inject private MyFactory myFactory;
private final Foo foo;
private final Bar bar;
public ParentClass() {
if(myFactory == null) System.err.println("Error: I should have injected by now!");
foo = myFactory.create(new Map<String, Object>());
// etc.
}
}
Заводской интерфейс
public interface MyFactory {
Foo create(Map<String, Object> mapA);
Bar create(Map<String, Object> mapB, Map<String, Object> mapC);
}
модуль
public class ParentModule extends AbstractModule {
@Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(Foo.class, FooImpl.class)
.implement(Bar.class, BarImpl.class)
.build(MyFactory.class));
}
FooImpl
public class FooImpl implements Foo {
private final Map<String, Object> mapA;
@AssistedInject
public FooImpl(@Assisted Map<String, Object> mapA) {
this.mapA = mapA;
}
}
BarImpl
очень похоже на FooImpl
, Что здесь не так? Обратите внимание, что я пробовал оба @AssistedInject
а также @Inject
здесь оба вызывают ошибку.
Выход:
Error: I should have injected by now!
Exception in thread "main" com.google.inject.ProvisionException: Guice provision errors:
1) Error injecting constructor, java.lang.NullPointerException
at ParentClass.<init>(ParentClass.java:7)
while locating com.my.package.ParentClass
1 error
at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:987)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
at com.my.package.ParentMain.main(ParentMain.java:16)
Caused by: java.lang.NullPointerException
at com.my.package.ParentClass.<init>(ParentClass.java:9)
at com.my.package.ParentClass$$FastClassByGuice$$d4b3063a.newInstance(<generated>)
at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
... 8 more
Обратите внимание, что строка 9 - это строка первого вызова myFactory.create()
2 ответа
Решение
Согласно Javadoc от Guice, полевая инъекция выполняется после конструкторской инъекции.
Я полагаю, ваш ParentClass
Экземпляр создан Guice. Когда ваш ParentClass
конструктор выполнен, его myFactory
поле еще не введено.
Две вещи. Чтобы использовать инъекцию в конструкторе, вы должны использовать инъекцию конструктора:
public class ParentClass {
private final Foo foo;
private final Bar bar;
@Inject
public ParentClass(MyFactory myFactory) {
if(myFactory == null) System.err.println("Error: I should have injected by now!");
this.foo = myFactory.create(new HashMap<String, Object>());
this.bar = myFactory.create(new HashMap<String, Object>(), new HashMap<String, Object>());
}
}
Кроме того, поскольку ваша фабрика имеет два параметра одного типа, вам необходимо назвать их:
public interface MyFactory {
Foo create(Map<String, Object> mapA);
Bar create(@Assisted("B") Map<String, Object> mapB, @Assisted("C") Map<String, Object> mapC);
}
а также
public class BarImpl implements Bar {
private final Map<String, Object> mapA;
private final Map<String, Object> mapB;
@AssistedInject
public BarImpl(@Assisted("B") Map<String, Object> mapA, @Assisted("C") Map<String, Object> mapB) {
this.mapA = mapA;
this.mapB =mapB;
}
}