通过注解动态生成注入
Dynamically generating injections by annotation
假设我有一个看起来像这样的 class:
public class MyClass {
@Inject
public MyClass(@Foo("whatever") Bar dependency) {
// ...
}
}
我想要一些自定义逻辑,可以看到我们正在注入一个类型为 Bar
的对象,并带有一个类型为 @Foo("whatever")
的注释,并构建一个相应的 Bar 对象......类似a Guice Provider
,但它获得了有关注射部位的更多上下文信息。 Guice 让我做那样的事吗?
您所描述的内容无法通过普通 Guice 实现:提供程序旨在成为零参数纯函数,并且无法像灵活的回调函数那样将注入站点信息插入其中。
不过,您可以通过两种不同的方式大致了解您想要的内容:
如果你知道每个 @Foo
参数的可能值,你可以让你的@Foo
成为binding annotation and bind it by providing a 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 可以将您的注入请求映射到一个提供者,而后者跳过 Guice 的映射,因此您可以自己 inspect/construct/inject 个实例。
如果您愿意跳过解决方案的注释部分,您可以注入 BarProvider
或 BarFactory
公开 forFoo(String)
方法,这将为您提供一致的注入无需提前知道所有 String 值。这将允许您使用 assisted injection or AutoFactory 来生成您的工厂(如果您希望每次调用生成一个实例),或者让您自己编写一个简单的工厂以增加灵活性。
public class MyClass {
private final Bar dependency;
@Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}
假设我有一个看起来像这样的 class:
public class MyClass {
@Inject
public MyClass(@Foo("whatever") Bar dependency) {
// ...
}
}
我想要一些自定义逻辑,可以看到我们正在注入一个类型为 Bar
的对象,并带有一个类型为 @Foo("whatever")
的注释,并构建一个相应的 Bar 对象......类似a Guice Provider
,但它获得了有关注射部位的更多上下文信息。 Guice 让我做那样的事吗?
您所描述的内容无法通过普通 Guice 实现:提供程序旨在成为零参数纯函数,并且无法像灵活的回调函数那样将注入站点信息插入其中。
不过,您可以通过两种不同的方式大致了解您想要的内容:
如果你知道每个
@Foo
参数的可能值,你可以让你的@Foo
成为binding annotation and bind it by providing a Annotation-compatibleequals
andhashCode
.这提供了最直观的体验:你可以用你的@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 可以将您的注入请求映射到一个提供者,而后者跳过 Guice 的映射,因此您可以自己 inspect/construct/inject 个实例。
如果您愿意跳过解决方案的注释部分,您可以注入 BarProvider
或 BarFactory
公开 forFoo(String)
方法,这将为您提供一致的注入无需提前知道所有 String 值。这将允许您使用 assisted injection or AutoFactory 来生成您的工厂(如果您希望每次调用生成一个实例),或者让您自己编写一个简单的工厂以增加灵活性。
public class MyClass {
private final Bar dependency;
@Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}