Я пытаюсь объединить эти 3 функции Guice: инъекцию, множественное связывание, дженерики. Я создаю прототип производственного проекта, вот он:
Во-первых, это небольшая иерархия для дженериков (в производственном случае существует иерархия из N сущностей):
public interface Type {
}
public class Type1 implements Type{
}
public class Type2 implements Type {
}
Затем классы ToCreate1 и ToCreate2 я хочу создать с помощью Factory.
Базовый класс:
public abstract class AbstractToCreate<T extends Type> {
public T type;
public Integer param;
public AbstractToCreate(T type, Integer param){
this.type = type;
this.param = param;
}
}
Это наследники:
public class ToCreate1 extends AbstractToCreate<Type1>{
@Inject
public ToCreate1(Type1 type, @Assisted Integer param) {
super(type, param);
}
}
public class ToCreate2 extends AbstractToCreate<Type2> {
@Inject
public ToCreate2(Type2 type, @Assisted Integer param) {
super(type, param);
}
}
Затем сам Factory:
public interface Factory<T extends Type> {
AbstractToCreate<T> create(Integer param);
}
Итак, теперь я хочу ввести карту, содержащую Factory
Итак, я создаю AbstractModule Guice с помощью метода настройки:
protected void configure() {
install(new FactoryModuleBuilder()
.implement(new TypeLiteral<AbstractToCreate<Type1>>(){}, ToCreate1.class)
.build(new TypeLiteral<Factory<Type1>>(){}));
install(new FactoryModuleBuilder()
.implement(new TypeLiteral<AbstractToCreate<Type2>>(){}, ToCreate2.class)
.build(new TypeLiteral<Factory<Type2>>(){}));
MapBinder<String, Factory> mapBinder = MapBinder.newMapBinder(binder(), String.class, Factory.class);
mapBinder.addBinding("type1").to(new TypeLiteral<Factory<Type1>>(){});
mapBinder.addBinding("type2").to(new TypeLiteral<Factory<Type2>>(){});
}
Итак, я ввожу его @Inject public Map<String, Factory> map;
, и все в порядке:
Factory<Type1> factory1 = main.map.get("type1");
Factory<Type2> factory2 = main.map.get("type2");
AbstractToCreate<Type1> create1 = factory1.create(1);//create1 is ToCreate1 instance
AbstractToCreate<Type2> create2 = factory2.create(2);//create2 is ToCreate2 instance
Как я упоминал ранее, в моей производственной системе гораздо больше типов, поэтому AbstractModule становится слишком громоздким. Я попытался избежать дублирования кода и модифицировал метод configure:
@Override
protected void configure() {
this.<Type1>inst(ToCreate1.class);
this.<Type2>inst(ToCreate2.class);
}
private <V extends Type> void inst(Class<? extends AbstractToCreate<V>> clazz) {
install(new FactoryModuleBuilder()
.implement(new TypeLiteral<AbstractToCreate<V>>(){}, clazz)
.build(new TypeLiteral<Factory<V>>(){}));
}
И не работает! Guice говорит:
1) ru.test.genericassistedinject.AbstractToCreate<V> cannot be used as a key; It is not fully specified.
Что случилось?