私は Guice の 3 つの機能 (注入、マルチバインディング、ジェネリック) を組み合わせようとしています。私は生産プロジェクトのプロトタイプを作成するので、ここにあります:
まず、これはジェネリックの小さな階層です (実稼働環境では、N 個のエンティティの階層があります)。
public interface Type {
}
public class Type1 implements Type{
}
public class Type2 implements Type {
}
次に、Factoryで作成したいクラスToCreate1とToCreate2。
基本クラス:
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<Type1>とFactory<Type2>を含むマップを注入して、ToInject1とToInject2をそれぞれ作成します。
そこで、 configure メソッドを使用して Guice のAbstractModuleを作成します。
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;
、すべてがOKです:
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>>(){}));
}
そして、それはうまくいきません!ギース 言います:
1) ru.test.genericassistedinject.AbstractToCreate<V> cannot be used as a key; It is not fully specified.
どうしたの?