我有两个使用post构造初始化的类,我需要根据vm参数注入其中一个。我在春天使用@Conditional注释完成了这种条件注入,但是我在CDI中找不到任何等价物。有人可以帮我这个。
代码就像这样,
public void impl1{
@PostConstruct
public void init(){
....
}
....
}
public void impl2{
@PostConstruct
public void init(){
...
}
....
}
如果vmargument type = 1,则必须注入impl1,如果type = 2,则必须注入impl2
答案 0 :(得分:2)
对于运行时决策(没有更改beans.xml),您基本上有两个选择:
选项1:使用生产者方法
@Produces
public MyInterface getImplementation() {
if(runtimeTestPointsTo1) return new Impl1();
else return new Impl2();
}
缺点:你使用new离开了bean的创建世界,因此你的Impl1和Impl2不能@Inject依赖。 (或你在生成器bean中注入两个变体并返回其中一个 - 但这意味着两个类型都将被初始化。)
选项2:使用CDI扩展
基本上听取processAnotated()并否决你不想要的一切。优秀的博客文章:http://nightspawn.com/rants/cdi-alternatives-at-runtime/
答案 1 :(得分:1)
可能最好的方法是使用扩展程序。您将创建两个类,它们具有相同的类型,因此它们有资格注入同一个注入点。然后,使用扩展名,您将禁用其中一个,只留下一个有效(另一个不会成为bean)。
扩展可以“挂钩”容器生命周期并影响它。您将希望利用ProcessAnnotatedType<T>
生命周期阶段(第一阶段之一)告诉CDI某个类应该是@Vetoed
。这意味着CDI会忽略它而不会变成bean。
请注意T
中的类型参数ProcessAnnotatedType<T>
- 将其替换为您的实现类型。然后,只有当CDI接收到该类时,才会通知观察者一次。或者,您可以将某些类型的T
替换为两种类型的impls(通常是一个接口),并且将同时通知观察者(然后您需要添加一个登录名以确定通知了哪个类)。 / p>
这是一个使用两个观察者的片段。他们每个人只会收到一次通知 - 当CDI收到给定的impl时 - 如果它与vm arg不同,则被否决:
public class MyExtension implements Extension {
public void observePAT(@Observes ProcessAnnotatedType<Impl1.class> pat){
// resolve your configuration option, you can alternatively place this login into no-args constructor and re-use
String vmArgumentType = loadVmArg();
// if the arg does not equal this impl, we do not want it
if (! vmArgumentType.equals(Impl1.class.getSimpleName())) {
pat.veto();
}
}
public void observePAT(@Observes ProcessAnnotatedType<Impl2.class> pat){
// resolve your configuration option, you can alternatively place this login into no-args constructor and re-use
String vmArgumentType = loadVmArg();
// if the arg does not equal this impl, we do not want it
if (! vmArgumentType.equals(Impl2.class.getSimpleName())) {
pat.veto();
}
}
}
答案 2 :(得分:0)
创建自己的@Qualifier并使用它来注入cdi bean:
public class YourBean {
@Inject
@MyOwnQualifier
private BeanInterface myEJB;
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface MyOwnQualifier {
YourCondition condition();
}