我无法找到如何拥有“动态AssistedInject”。 我的意思是,我想向工厂提供它需要在运行时根据参数使用的实现类名。 这是我现在拥有的:
interface Letter {}
abstract class ALetter implements Letter {
public ALetter(T1 t1, T2 t2) {...}
}
class A implements Letter {
public static final NAME = "A";
@Inject
public A(@Assisted T1 t1, T2 t2) { super(t1, t2); }
}
class B implements Letter {
public static final NAME = "B";
@Inject
public B(@Assisted T1 t1, T2 t2) { super(t1, t2); }
}
我希望能够根据他们的名字加载A或B,考虑到我会有T1,但我需要注入T2。 它可能看起来像:
class MyClass {
@Inject
public MyClass(RequestData data, MyConfig config, ILetterFactory letterFactory) {
Letter letter = letterFactory.get(data.getLetterName(), config.getT2());
}
}
我会使用类似的东西配置ILetterFactory:
install(new FactoryModuleBuilder().build(ILetterFactory.class));
但是我知道这当前不会起作用,因为lettername不是我的构造函数的真正参数,而Guice就是不能那样工作。它应该让你知道我想要的东西。
我目前找到的唯一解决方案是不使用Guice:我有自己的工厂,根据名称解析类构造函数(通过Map<String, Constructor>
),并调用newInstance
提供它适当的参数(除了工厂本身之外根本没有注射)。
有没有办法使用Guice来避免自己创建该工厂? 感谢
答案 0 :(得分:1)
FactoryModuleBuilder没有您想象的那么强大 - 它没有在实现之间切换的规定,并且仅用于将注入的依赖项与其他构造函数参数混合。幸运的是,Guice使您的工厂易于编写。你正在寻找的是这个界面的实现:
public interface ILetterFactory {
/** This assumes that T2 is a Guice-satisfied dependency,
* and not meant to be @Assisted, so leave it out of the interface. */
Letter get(String which);
}
选择一个是让Guice为您的实例提供一个Provider,如果你的Letters有很多不同的deps,或者你的deps列表很长或经常更改,那么这个最有用。如果A和B需要辅助依赖项,请将Provider<A>
替换为您通过FactoryModuleBuilder绑定的A.Factory
。
public class LetterFactory implements ILetterFactory {
@Inject Provider<A> aProvider;
@Inject Provider<B> bProvider;
@Override public Letter get(String which) {
if (A.NAME.equals(which)) {
return aProvider.get();
} else if (B.NAME.equals(which)) {
return bProvider.get();
} else {
throw new IllegalArgumentException("Letter does not exist");
}
}
}
选择二,你负责从Guice创建一个新实例。如果你的deps列表发生变化,它需要更多的维护,并且不能很好地与AOP和其他类似的功能一起使用,但如果你的Letters需要辅助参数和一小组类似的deps,可能会少一些工作:
public class LetterFactory implements ILetterFactory {
@Inject Provider<T2> t2Provider;
@Override public Letter get(String which) {
if (A.NAME.equals(which)) {
return new A(t2Provider.get());
} else if (B.NAME.equals(which)) {
return new B(t2Provider.get());
} else {
throw new IllegalArgumentException("Letter does not exist");
}
}
}