如何将引用模块中的字段的匿名提供程序移动到单独的类中?

时间:2017-02-03 00:59:42

标签: java guice inner-classes

玩具示例:

public class MyModule extends AbstractModule {
  private static final Foo foo;

  public MyModule(Foo foo) {
    this.foo = foo;
  }

  @Override
  public void configure() {
    bind(Bar.class).toProvider(new Provider<Bar>() {
      @Override public Bar get() {
        return foo.getBar();
      }
    });
  }
}

这让我可以懒惰地调用存储在.getBar()字段中的用户提供的Foo实例的MyModule方法。但是现在provider has its own dependencies - 因此我需要定义一个非匿名类,我指定一个@Inject构造函数。类似的东西:

public class MyModule extends AbstractModule {
  private static final Foo foo;

  public MyModule(Foo foo) {
    this.foo = foo;
  }

  @Override
  public void configure() {
    bind(Bar.class).toProvider(BarProvider.class);
  }

  BarProvider implements Provider<Bar> {
    private Baz baz;

    @Inject BarProvider(Baz baz) {
      this.baz = baz;
    }

    @Override public Bar get() {
      return foo.getBar(baz);
    }
  }
}

完美!除了Guice doesn't like this ...

  

线程“main”com.google.inject.CreationException中的异常:无法创建注入器,请参阅以下错误:

     

1)不支持注入内部类。请使用'static'类(顶级或嵌套)而不是com.example.MyModule $ BarProvider。

所以,我陷入困境。我需要同时访问模块上的字段和Provider类的注入类型。有没有办法做到这一点?

注意:这个玩具示例排除了一些实际的复杂性 - 特别是bind()语句更复杂,这就是为什么我不能简单地定义@Provides方法

2 个答案:

答案 0 :(得分:2)

在某种程度上,注入内部类是不可能的,因为Guice不能反射性地创建没有外部父实例的内部实例(相当于奥术outerInstance.new InnerInstance()语法)。

一些选项:

  • 通过您的图表使Foo可注入,可能隐藏在PrivateModule中,因此它不会暴露给您的整个图表(如果这对您很重要)。
  • 使用匿名内部提供程序(或提取的等效项),并从AbstractModule的getProvider(Class<T>)方法获取Provider<Baz>。如果你在创建Injector之前尝试调用它,你会得到一个例外,但是为了按照你正在做的方式创建一个Provider,这可能不是问题。
  • 将您的bind发布到玩具问题之外,看看@Provides是否有可能带来一些聪明才智。

相关:Accessing Guice injector in its Module?

答案 1 :(得分:0)

我意识到我让Guice为我构建我的Provider,我实际上并不需要这样做。尽管Guice文档中的示例传递DatabaseTransactionLogProvider.class与第一个片段更好的并行,但是手动构建我的Provider实例,并传入Foo实例和{ {1}}实例(provided by the module)。

Provider<Baz>