根据条件注入基于@EJB的bean

15
一个新手问题:我能否根据在属性文件中设置的条件注入不同的bean?这是我想要实现的:
我在属性文件中设置了一些值。如果它为true,那么我想要...
  public class MyClass{
    @EJB
    private MyBean bean;
  }

如果它是假的,那么

public class MyClass{
  @EJB
  private MyBean2 bean2;
 }

这可行吗?


执行JNDI查找将是一个可行的替代方案,可以产生相同的后置条件,但在应用服务器之间迁移代码将很困难,因为到EJB的默认JNDI路径没有标准化。 - 8bitjunkie
2个回答

28
正如Gonzalo所说,如果你想将其声明为类字段并使用不同的实现,首先需要指定bean的公共接口。
此外,我认为你可以更优雅地使用CDI的@Produces方法来实现;即在以下几行之间:
@Singleton
@Startup
public class Configuration {

    private boolean someCondition;

    @PostConstruct
    private void init() {
        someCondition = ... // get a value from DB, JMS, XML, etc.
    } 

    @EJB(lookup="java:comp/env/myParticularBean")
    MyBean myBean1;

    @EJB(beanName="anotherTypeOfBeanInjectedByName")
    MyBean myBean2;

    @Produces
    public MyBean produceMyBean() {
        if (someCondition)
            return myBean1;
        } else {
            return myBean2;
        }
    }
}

然后在你的代码中,你可以直接使用:
@Inject
MyBean myBean;

根据您的情况,将为您注入适当的bean。
如果您不需要在类级别上使用字段,可以使用旧的方式并在JNDI中定位EJB - 这样您就可以控制要定位和使用的bean的类型。
编辑:我已经添加了@EJB注释的bean,以显示'myBean1'和'myBean2'实例可能来自哪里。
这个例子表明,您可以有一个单一的地方,在那里定义所有不同EJB实现和其他组件的依赖关系。例如,这可以实现为具有@EJB字段、@PersistenceContext字段等的单例EJB。
与所呈现的方式相比,您可以将"return myBean1"更改为类似"return context.lookup("JNDI_NAMESPACE_COORDINATES")"的内容,其中"context"是"InitialContext"的一个实例。
希望这样更清楚明白。

myBean1和myBean2是实现了MyBean接口的类的实例。我将更新问题以展示更多的代码。 - Piotr Nowicki
谢谢PedroKowalski。那么应该在哪个类中编写“public MyBean produceMyBean()”方法呢? - neo
@neo 无论适合你哪种方式 :-) 如果你想使用@EJB,它可以是Singleton EJB,就像示例中所示。如果您更喜欢手动使用JNDI查找,则可以是常规类。 - Piotr Nowicki
谢谢并请查看示例 - 希望这次更清楚。 - Piotr Nowicki
我尝试过为EJB接口定义一个@Produces方法,并为实现相同接口的@EJB定义了一个实现,这会为容器创建一个模糊的依赖问题。 - PålOliver
显示剩余2条评论

2

我认为您无法修改被注入的bean的类型。我想这是Java的限制,因为它是一种强类型语言 :)

但是,您可以有这样的情况:多个bean实现了相同的接口,并且您想要注入该接口的特定实现,如下所示:

@Local
public interface MyBean {
}

@Stateless
public class MyBeanImpl1 implements MyBean {
}

@Stateless
public class MyBeanImpl2 implements MyBean {
}

那么你可以这样做:

public MyClass {

@EJB(beanName="MyBeanImpl1")
MyBean myBean;

}

或者

public MyClass {

@EJB(beanName="MyBeanImpl2")
MyBean myBean;

}

根据您想要注入的实现方式。


不是一个很好的解决方案,因为如果你决定改变实现方式,就必须重新编译代码。 - Guido
实际上,@Neo 要求基于条件的注入,而不是手动选择注入。 - Artem Novikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接