无法使用 guice 注入

Unable to inject using guice

我有一个档案 class 具有以下结构:

public class Archive implements Tasklet, StepExecutionListener{

    @Inject
    private Configuration configuration;
    public static final String FF = "ff";

    @Override
    public RepeatStatus execute(StepContribution arg0, ChunkContext arg1)
            throws Exception {

        System.out.println("in execute method :)");
        return RepeatStatus.FINISHED;
    }


    @Override
    public ExitStatus afterStep(StepExecution arg0) {
        return ExitStatus.COMPLETED;
    }

    @Override
    public void beforeStep(StepExecution arg0) {
        JobExecution jobExecution = arg0.getJobExecution();
         ExecutionContext jobContext = jobExecution.getExecutionContext();
         Properties properties = configuration.getPrefixProperties(FF);
         filePath =  properties.getProperty("fd.folder");
         fileName = "test.csv";

    }
}

我的活页夹 class 看起来像这样:

@Singleton
public class EWM extends AbstractModule {

    @Inject
    private static Injector injectorInstance;

    private static final EWM instance = new EWM();

    public static final EWM getInstance() {
        return instance;
    }

    public static Injector getInjector() {
        return injectorInstance;
    }

    public EWM() {
    }

    @Override
    protected void configure() {    
        bind(Archive.class);
        requestInjection(LoggingAspect.class);  
    }
}

我得到空配置对象。我无法弄清楚配置为空的原因。谁能帮我找出原因。

你的问题中没有足够的信息来回答它,但我可以给你一些建议,告诉你去哪里找。

Guice 试图阻止注入 null,因此很可能根本没有注入 Archive。可能发生的原因有几个:

  • Archive 有一个 @Inject 构造函数,它没有设置 configuration 字段
    • Guice 可能会选择注入此构造函数而不是 @Inject 字段(如果两者都可用)。从构造函数中删除 @Inject 注释。
  • 实例化 Archive 的人不是 Guice。
    • 您是否使用 Injector#getInstance() 直接实例化 Archive,它是否传递了注入器正在实例化的对象上的一个字段?

我怀疑 configuration 为空的原因是因为 class 不是由 Guice 创建的。

为防止这种情况发生,为 Guice 设计的 classes 提供包范围或私有构造函数:

public class Archive implements Tasklet, StepExecutionListener {
  private static final String FF = "ff";
  private final Configuration configuration;

  @Inject
  Archive(Configuration configuration) {
    this.configuration = configuration;
  }

  ...

我选择了包范围的构造函数,因为我想为 class 编写单元测试(参见下面的注释)。

如果你想让Archive成为单例,用@Singleton

注释class

这里是上面的一个简单模块class:

public class ArchiveModule extends AbstractModule {

  @Override
  protected void configure() {
    bind(Archive.class);
  }
}

实际上并不需要 bind() 调用——实际上也不需要模块——但我喜欢它,所以我知道如果安装了模块,Guice 将在注入器创建时给出错误如果它无法为 Archive class.

创建依赖项

在您的 main 中,您的代码看起来像这样:

Main main = Guice.createInjector(
    new ArchiveModule(),
    new AnotherModule(),
    ... );
main.run();

一些注意事项:

  • 将@Singleton 添加到您的模块没有任何效果,因为 Guice 不构建模块;要求 Guice 创建注入器的代码通常会构建模块。
  • 同样,你的模块没有被注入,所以你的模块的 injector 字段永远不会被设置(除非你请求对模块进行静态注入,但我强烈建议不要那样做)
  • 优先使用构造函数注入而不是字段注入,因此 1) 您的字段可以是最终的,2) 您可以编写单元测试来创建对象而不使用 Guice,并且 2) 很难意外地创建 class没有 Guice 的生产代码。
  • 我建议不要对 class 名称使用缩写,除非缩写是众所周知的