假设我有一个类似这样的类:
public class MyClass {
@Inject
public MyClass(@Foo("whatever") Bar dependency) {
// ...
}
}
我希望有一些自定义逻辑,可以看到我们正在注入一个类型为Bar
的对象,注释类型为@Foo("whatever")
,并构造一个相应的Bar对象...类似于Guice Provider
,但这会获得有关注射部位的更多上下文信息。 Guice让我做那样的事吗?
答案 0 :(得分:3)
通过普通Guice无法实现您所描述的内容:提供者旨在成为零参数纯函数,并且无法像将灵活的回调函数那样将注入站点信息转换为它们。
您可以通过两种不同的方式估算出您想要的内容:
如果您知道 @Foo
参数的每个可能值,您可以将@Foo
设为binding annotation并通过提供来绑定它一个Annotation-compatible equals
and hashCode
。这提供了最直观的体验:您可以使用@Foo
对任何其他类型执行任何操作,例如在构造函数中使用@Foo
或注入@Foo("value") Provider<Bar> barProvider
。
@Override public void configure() {
for (String value : PREDEFINED_VALUES) {
bind(Bar.class)
.annotatedWith(new FooImpl(value))
.toProvider(new BarProvider(value));
}
}
如果您希望@Foo
适用于任意参数,则需要使用custom injections扩展Guice。这不适用于构造函数注入或与任何其他@Inject
注释一起使用,但它允许您在Guice注入完成后检查类型以根据需要增加它们(例如,检测并响应@Foo
字段上的注释)。
有关详细信息,请参阅the example in the Guice docs。
在内部,Guice的核心实际上是Map<Key, Provider>
,其中Key表示一对可能参数化的类型和可选的绑定注释。之前的绑定注释技巧很有效,因为Guice可以将注入请求全部映射到Provider,后者跳过Guice的映射,这样您就可以自己检查/构造/注入实例。
如果您愿意跳过解决方案的注释部分,可以注入一个BarProvider
或BarFactory
公开forFoo(String)
方法,这样可以在不知道的情况下为您提供一致的注射提前所有的String值。这样您就可以使用assisted injection或AutoFactory生成工厂(如果您希望每次调用生成一个实例),或者让您自己编写一个简单的工厂以增加灵活性。
public class MyClass {
private final Bar dependency;
@Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}