【问题标题】:Error injecting a class with generic type @Inject Guice注入泛型类型@Inject Guice 的类时出错
【发布时间】:2017-05-29 19:15:44
【问题描述】:

我正在尝试使用带有 @Inject 注释的 Guice 在另一个类(比如 ClassB)中注入一个通用类型的类(比如 ClassA)。被注入的类的代码如下所示:

public interface InterfaceA<T> {

}

public class ClassA<T> implements InterfaceA<T> {
    private final Class<T> data;
    private Dependency1 dependency1;

    @Inject
    public ClassA(Class<T> data, Dependency1 dependency1) {
        this.data = data;
        this.dependency1 = dependency1;
    }

}

ClassB的代码如下:

public class ClassB {
    private InterfaceA<Entity1> interfaceA;

    @Inject
    public ClassB(InterfaceA<Entity1> interfaceA) {
        this.interfaceA = interfaceA;
    }
}

模块类如下:

public class MyModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(new TypeLiteral<InterfaceA<Entity1>>(){}).to(new TypeLiteral<InterfaceA<Entity1>>(){});
    }
}

但是,当应用程序启动时,它会给出以下错误:

ERROR [2017-01-14 19:54:00,646] com.hubspot.dropwizard.guice.GuiceBundle: Exception occurred when creating Guice Injector - exiting
! com.google.inject.CreationException: Unable to create injector, see the following errors:
! 
! 1) Could not find a suitable constructor in java.lang.Class. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
!   at java.lang.Class.class(Class.java:119)

任何有关如何解决此问题的意见都会非常有帮助。提前致谢。

【问题讨论】:

  • 您为什么要尝试将Class&lt;T&gt; 注入某些东西?你知道模块中的类型不是重点吗?
  • 我想注入它,因为我想知道在运行时注入的类的类型。
  • 这似乎违背了面向对象编程的观点。而且所有类都有.getClass 方法,这还不够吗?
  • 在上述场景中你将如何使用.getClass 方法?我想知道:)
  • 我不想将此作为答案发布,因为我很可能不理解您,但我指的是public ClassA(Dependency1 dependency) { this.data = dependency.getClass(); /* etc. */ }

标签: java generics dependency-injection guice inject


【解决方案1】:

您不能以声明方式执行此操作。您必须使用提供者方法:

public class MyModule extends AbstractModule {
  @Override protected void configure() {}

  @Provides InterfaceA<Entity1> provideInterfaceAEntity1(Dependency1 dep) {
    return new ClassA<Entity1>(Entity1.class, dep);
  }
}

这是唯一的方法,因为您不能自动将Class&lt;T&gt; 注入ClassA

你需要在你的Module 中为每个你想与InterfaceA 耦合的Entity 使用这样的方法。

【讨论】:

  • 感谢您的解决方案!但是,在这种情况下,我们将 ClassA 的所有依赖项移到该类之外,这似乎不是一种干净的方式。此外,我们在这里没有使用 Guice 的 @Inject 功能,而是使用 new() 创建一个新对象。我找到了另一种方法来做到这一点。查看我的解决方案。
  • @user3375226 Guice 不禁止使用new。使用@Inject 甚至不是强制性的。更重要的是,Guice 建议构造函数请求最终对象。使用literal.getRawType(),您就违反了该建议。我相信这个解决方案是最 Guice-y 的。
【解决方案2】:

我终于找到了解决办法。在这里,我不是在 ClassA 的构造函数中注入 Class&lt;T&gt; data,而是注入 TypeLiteral&lt;T&gt; literal 并使用它的 getRawType() 方法从 TypeLiteral 读取类类型。

ClassA的代码如下:

public class ClassA<T> implements InterfaceA<T> {
    private final Class<? super T> data;
    private Dependency1 dependency1;

    @Inject
    public ClassA(TypeLiteral<T> literal, Dependency1 dependency1) {
        this.data = literal.getRawType();
        this.dependency1 = dependency1;
    }
}

其他类的其余代码保持不变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    相关资源
    最近更新 更多