我有一个 REST 控制器
@Path("/greet")
@RequestScoped
public class GreetController {
@Inject
private GreeterService greeterService;
@GET
@Path("{name}")
@Produces(TEXT_PLAIN)
public String greet(@PathParam("name") String name) {
return greeterService.greet(name);
}
}
使用迎宾员服务
@RequestScoped
public class GreeterService {
@Inject
private Greeter greeter;
public String greet(String name) {
return greeter.greet(name);
}
}
GreeterService 本身注入了一个具有两个实现的接口
@RequestScoped
@Hello
public class HelloGreeter implements Greeter {
@Override
public String greet(String name) {
return "Hello " + name;
}
}
和
@RequestScoped
@Whazzup
public class WhazzupGreeter implements Greeter {
@Override
public String greet(String name) {
return "Whazzup " + name;
}
}
@Whazzup
和@Hello
只是限定词。
我正在尝试根据 GreetController 中使用的限定符将Greeter
接口的正确实现注入到GreeterService
中。 使用CDI甚至可以做到这一点吗? 一个简单的解决方法当然是为每个限定符设置两个GreeterService
,但这似乎是一个坏主意,因为添加新的限定符时GreeterService
s 的计数会增加。
当然,这只是一个基本的例子,GreeterServcie是不必要的,但我不允许将我的公司代码发布到StackOverflow,所以我不得不实现一个简单的例子来重现我们的架构。
提前感谢!
要注入限定的事物,请确保限定符出现在事物和注入点上:
@Inject
@Special
private Thing thing;
@Produces
@Special
private Thing makeSpecialThing() {
return someSpecialThingCreatedOrGottenFromSomewhere;
}
从您之前的一些评论来看,您似乎已经知道这一点,并且出于任何(可能有效,可能无效(的原因,您都不想这样做。
要在运行时动态地选择一件事,即一旦您的应用程序启动,就像您可能想要的那样,您可以使用Instance
公开的工具(为了(希望(清晰,我在下面故意制作了过于冗长的示例:
final Instance<Object> instance = ... // get an Instance, e.g. via CDI.current() or BeanManager.createInstance()
final Instance<Thing> anyAndAllThings = instance.select(Thing.class);
final Instance<Thing> onlyTheSpecialThing = anyAndAllThings.select(new AnnotationLiteral<SpecialThing>() {});
final Thing theSpecialThing = onlyTheSpecialThing.get();
此模式允许您随时选择是需要符合Hello
条件的Greeter
还是需要符合Whazzup
条件的Greeter
。
通常,在运行时而不是启动时执行此类工作的愿望只是更大的问题冰山一角,但在某些情况下可能是有效的。