如何将引用模块中字段的匿名提供者移动到单独的类中?
Posted
技术标签:
【中文标题】如何将引用模块中字段的匿名提供者移动到单独的类中?【英文标题】:How to move an anonymous Provider that references fields in the module into a separate class? 【发布时间】:2017-02-03 00:59:41 【问题描述】:玩具示例:
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();
);
这让我可以懒惰地调用存储在MyModule
字段中的用户提供的Foo
实例的.getBar()
方法。但是现在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) 不支持注入内部类。请使用“静态”类(***或嵌套)而不是 com.example.MyModule$BarProvider。
所以,我陷入了困境。我需要同时访问模块上的字段和来自Provider
类的注入类型。有没有办法做到这一点?
注意:这个玩具示例排除了一些实际的复杂性——尤其是bind()
语句涉及更多,这就是为什么我不能简单地定义一个@Provides
方法。
【问题讨论】:
【参考方案1】:在某种程度上,注入内部类是不可能的,因为 Guice 无法在没有外部父实例的情况下反射地创建内部实例(相当于神秘的 outerInstance.new InnerInstance()
语法)。
一些选项:
使 Foo 可通过您的图表进行注入,可能隐藏在 PrivateModule 中,因此它不会暴露在您的整个图表中(如果这对您很重要的话)。 使用匿名的内部 Provider(或提取的等价物),并从 AbstractModule 的getProvider(Class<T>)
方法中获取 Provider<Baz>
。如果您尝试在创建 Injector 之前调用它,您会得到一个异常,但是对于您正在做的方式创建一个 Provider,这可能不是问题。
在玩具问题之外发布您的bind
,看看@Provides
是否可以通过一些聪明才智来实现。
相关:Accessing Guice injector in its Module?
【讨论】:
谢谢杰夫!发布后我意识到我需要的是getProvider()
。它正盯着我的脸,但由于某种原因它没有点击:)【参考方案2】:
我意识到让 Guice 为我构建我的 Provider
让我感到厌烦,而我实际上并不需要这样做。尽管 Guice 文档中的示例传递了 DatabaseTransactionLogProvider.class
,但与第一个 sn-p 更好的并行将是手动构造我的 Provider
的实例,并同时传递 Foo
实例和 Provider<Baz>
实例( provided by the module)。
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 BarProvider(foo, getProvider(Baz.class));
static BarProvider implements Provider<Bar>
private final Foo foo;
private final Provider<Baz> bazProvider;
BarProvider(Foo foo, Provider<Baz> bazProvider)
this.foo = foo;
this.bazProvider = bazProvider;
@Override public Bar get()
return foo.getBar(bazProvider.get());
【讨论】:
以上是关于如何将引用模块中字段的匿名提供者移动到单独的类中?的主要内容,如果未能解决你的问题,请参考以下文章