wul*_*pro 4 java dependency-injection guice
如果我有以下课程:
public class ObjectDAOMongoDBImpl<T> extends GenericDAOMongoDBImpl<T, ObjectId> implements ObjectDAO<T> {
public ObjectDAOMongoDBImpl(Class<T> entityClass, Mongo mongo, Morphia morphia, String dbName) {
super(entityClass, mongo, morphia, dbName);
}
}
Run Code Online (Sandbox Code Playgroud)
其中,entityClass提供在运行时-我该如何使用吉斯到上述类型的接口绑定?
public class RunnerModule extends AbstractModule {
@Override
protected void configure() {
bind(GenericDAO.class).to(ObjectDAOMongoDBImpl.class);
}
}
public class Runner<T, V> {
GenericDAO<T, V> dao;
@Inject
public Runner(GenericDAO<T, V> dao) {
this.dao = dao;
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new RunnerModule());
injector.getInstance(Runner.class);
}
}
Run Code Online (Sandbox Code Playgroud)
可以定义mongo,morphia和dbName作为文字RunnerModule(是否有更简洁的方法?),但我无法知道什么entityClass是运行时.
这不是Guice惯用的,也不是它的主要焦点.
jfpoilpret已经说了所有可以说的,但我想从另一个方向解决问题,你可以选择(可能)通过失去类型安全来解决你的问题.
因此,在您的代码中,您要求Guice Runner<T, V>像这样获取您的类的实例
injector.getInstance(Runner.class);
Run Code Online (Sandbox Code Playgroud)
但Guice无法解决这个问题,因为Runner<T, V>它具有依赖性GenericDAO<T, V>,但您没有绑定它的确切实现.正如jfpoilpret所说,你必须在你的模块中为它绑定一些具体的实现.
我猜你想根据一些输入数据确定GenericDAO<T, V>传递给你的确切实现Runner<T, V>,这些数据的类型在编译时是未知的.现在,我们假设您有两个实现.
bind(new TypeLiteral<GenericDAO<String, ObjectID>>(){}).to(StringDAO.class);
bind(new TypeLiteral<GenericDAO<Double, ObjectID>>(){}).to(IntegerDAO.class);
Run Code Online (Sandbox Code Playgroud)
根据不同类型的输入,您可以执行此操作
Injector injector = Guice.createInjector(new RunnerModule());
// possible input which you get from *somewhere* dynamically
Object object = 1.0;
TypeLiteral<?> matchedTypeLiteral = null;
for (Key<?> key : injector.getAllBindings().keySet()) {
TypeLiteral<?> typeLiteral = key.getTypeLiteral();
Type type = typeLiteral.getType();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
if (parameterizedType.getRawType() == GenericDAO.class) {
List<Type> actualTypeArguments = Arrays.asList(parameterizedType.getActualTypeArguments());
if (actualTypeArguments.get(0) == object.getClass())
matchedTypeLiteral = typeLiteral;
}
}
};
Runner<?, ?> runner = new Runner<>((GenericDAO<?, ?>) injector.getInstance(Key.get(matchedTypeLiteral)));
System.out.println(runner.dao.getClass()); // IntegerDAO.class
Run Code Online (Sandbox Code Playgroud)
如果Object object = "string";,那么将找到其他实现.这当然相当丑陋,可以通过检查子类和东西来改进,但我认为你明白了.最重要的是你无法解决这个问题.
如果你设法做到(绕过它),请给我发电子邮件,因为我想知道它!我不久前遇到了同样的问题.我写了一个简单的BSON编解码器,我想根据某些任意输入的类型加载通用接口的特定实现.这适用于Java-to-BSON映射,但我不能以任何合理的方式做到这一点,所以我选择了一个更简单的解决方案.