Java 如何将类注入到';类别<&燃气轮机;clazz';在Guice?
我有一个带构造函数的类,例如:Java 如何将类注入到';类别<&燃气轮机;clazz';在Guice?,java,dependency-injection,guice,Java,Dependency Injection,Guice,我有一个带构造函数的类,例如: @Inject public ClassTest(ITestInterface testInterface, Class<?> clazz){ ... } @Inject 公共类测试(ITestInterface testInterface,Class clazz){ ... } 问题是如何将一个类绑定到一个可以注入这个构造函数的实现上,并且ClassTest绑定会选择正确的类吗 我想在不同的时间点注入不同的类。当我试图解决它时,G
@Inject
public ClassTest(ITestInterface testInterface, Class<?> clazz){
...
}
@Inject
公共类测试(ITestInterface testInterface,Class clazz){
...
}
问题是如何将一个类绑定到一个可以注入这个构造函数的实现上,并且ClassTest
绑定会选择正确的类吗
我想在不同的时间点注入不同的类。当我试图解决它时,Guice给出了一个错误,它无法在
java.lang.Class
上找到任何合适的构造函数。要随时间改变注入值,您可以使用提供程序。然后它可能看起来像这样:
模块配置:
public class SomeModule extends AbstractModule{
@Override
protected void configure() {
bind(Class.class).toProvider(SomeProvider.class);
}
}
提供者(不是很优雅,但可能是一个开始…):
客户机代码示例:
public static void main(String[] args){
SomeProvider.setClass(SomeClass.class);
Injector injector = Guice.createInjector(new SomeModule());
printFields(injector.getInstance(Class.class));
SomeProvider.setClass(SomeOtherClass.class);
printFields(injector.getInstance(Class.class));
}
private static void printFields(Class clazz) {
Field[] declaredFields = clazz.getDeclaredFields();
for(Field field : declaredFields){
System.out.println(field.getName());
}
}
最后的结果是:
itWorks
itWorksGreat
我认为您必须使用Guice的扩展
基本上,您可以按原样定义类测试
,但将“变化”依赖项标记为@Assisted
:
@Inject
public ClassTest(ITestInterface testInterface, @Assisted Class<?> clazz){
...
}
然后安装特殊类型的模块,为您创建工厂:
// Inside your module
install(new FactoryModuleBuilder().build(ClassTestFactory.class));
然后,无论您需要什么样的ClassTest
实例,都应该插入ClassTestFactory
接口:
@Inject
YourLogicClass(ClassTestFactory ctFactory) {
this.ctFactory = ctFactory;
}
最后,您可以使用它为您想要的每个类对象创建ClassTest
s:
ClassTest ct1 = ctFactory.create(SomeClass.class);
ClassTest ct2 = ctFactory.create(AnotherClass.class);
但是如果我是你,我真的会重新考虑整个类体系结构,以避免这些事情的需要。即使没有辅助注入,也可以解决这个问题,只需在创建绑定时使用
TypeLiteral
:
import javax.inject.Inject;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
public class ClassTest
{
static interface ITestInterface {}
@Inject
public ClassTest(ITestInterface testInterface, Class<?> clazz)
{
System.err.println("testInterface=" + testInterface);
System.err.println("clazz=" + clazz);
}
public static void main(String... argument)
{
ITestInterface testObject = new ITestInterface() {};
Module module = new AbstractModule()
{
@Override
protected void configure()
{
binder().bind(ITestInterface.class).toInstance(testObject);
binder().bind(new TypeLiteral<Class<?>>() {}).toInstance(testObject.getClass());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
};
Injector injector = Guice.createInjector(module);
injector.getInstance(ClassTest.class);
}
}
不过,我必须同意@VladimirMatveev的观点,这是一个有点不寻常的用例,需要注入java.lang.Class
对象可能表明存在设计缺陷。我遇到的这种类型的注入的唯一看似有效的例子是类型检查,其中注入的类需要class
对象来检查其他对象的类型(通过class.isInstance(…)
),但不希望注入该类的实例(!)(例如,因为它不是一个单例,可能会产生各种其他不想要的对象创建)。尽管如此,即使是这种情况也有点胡闹,可能会以更好的方式解决。
至少,我会使用一个更具体的类型参数,比如ClassYou永远不应该编写这样的提供程序!它违背了DI概念的全部原因,而且确实是Guice试图删除的东西。嗯……你是对的(不过这仍然是可能的)对你的回答,这真的很好,我不知道这样的解决方案。我想我可以利用它解决我遇到的两个问题
@Inject
YourLogicClass(ClassTestFactory ctFactory) {
this.ctFactory = ctFactory;
}
ClassTest ct1 = ctFactory.create(SomeClass.class);
ClassTest ct2 = ctFactory.create(AnotherClass.class);
import javax.inject.Inject;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
public class ClassTest
{
static interface ITestInterface {}
@Inject
public ClassTest(ITestInterface testInterface, Class<?> clazz)
{
System.err.println("testInterface=" + testInterface);
System.err.println("clazz=" + clazz);
}
public static void main(String... argument)
{
ITestInterface testObject = new ITestInterface() {};
Module module = new AbstractModule()
{
@Override
protected void configure()
{
binder().bind(ITestInterface.class).toInstance(testObject);
binder().bind(new TypeLiteral<Class<?>>() {}).toInstance(testObject.getClass());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
};
Injector injector = Guice.createInjector(module);
injector.getInstance(ClassTest.class);
}
}
testInterface=ClassTest$1@3d921e20
clazz=class ClassTest$1