如果我有以下类(class):
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);
}
}
在运行时提供 entityClass
- 我如何使用 guice 将所述类型绑定(bind)到接口(interface)?
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);
}
}
可以将 mongo
、morphia
和 dbName
定义为 RunnerModule
的文字(有没有更干净的方式?),但直到运行时我才知道 entityClass
是什么。
最佳答案
这不是 Guice 惯用的做法,也不是它的主要关注点。
jfpoilpret 已经说了所有可以说的,但我想从另一个方向来解决这个问题,您可以选择(可能)通过失去类型安全来解决您的问题。
因此,在您的代码中,您要求 Guice 获取 Runner<T, V>
的一个实例像这样上课
injector.getInstance(Runner.class);
但这不能由 Guice 解决,因为 Runner<T, V>
依赖于 GenericDAO<T, V>
,但您没有为它绑定(bind)一个确切的实现。因此,正如 jfpoilpret 所说,您必须在模块中为其绑定(bind)一些具体实现。
我猜您想确定确切的 GenericDAO<T, V>
您传递给 Runner<T, V>
的实现基于一些输入数据,编译时不知道哪些数据的类型。现在,假设您有两个实现。
bind(new TypeLiteral<GenericDAO<String, ObjectID>>(){}).to(StringDAO.class);
bind(new TypeLiteral<GenericDAO<Double, ObjectID>>(){}).to(IntegerDAO.class);
根据不同类型的输入,你可以这样做
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
如果Object object = "string";
,然后将找到其他实现。这当然是相当丑陋的,可以通过检查子类和东西来改进,但我想你明白了。最重要的是,您无法解决这个问题。
如果你设法做到了(绕过它),请给我发一封电子邮件,因为我想知道这件事!不久前,我遇到了与您面临的相同问题。我写了一个简单的 BSON codec我想根据一些任意输入的类型加载通用接口(interface)的特定实现。这适用于 Java 到 BSON 的映射,但我无法以任何明智的方式反过来做,所以我选择了一个更简单的解决方案。
关于java - 使用 guice 将运行时参数传递给构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8147527/