相当于CDI中的@Conditional

时间:2017-04-12 05:39:56

标签: java cdi inject

我有两个使用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

3 个答案:

答案 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();
}