在 JEE 中使用生产者和具有 CDI 的多态性添加有状态 bean
Posted
技术标签:
【中文标题】在 JEE 中使用生产者和具有 CDI 的多态性添加有状态 bean【英文标题】:Add a stateful bean using a producer and polymorphism with CDI in JEE 【发布时间】:2017-09-11 10:12:17 【问题描述】:我真的是 JEE CDI 的新手,但昨晚试了半天才找到问题的解决方案。
我有一个控制器类,当调用启动时,它应该根据参数使用生产者注入一个有状态的 bean。这个提到的有状态 bean 本身包含一个注入的 bean。
说实话,不确定这是否有效,非常感谢任何反馈=)
这里有一些虚拟代码可以帮助理解我想要做什么(基于https://docs.jboss.org/weld/reference/1.0.0/en-US/html/producermethods.html)。可能我现在完全搞砸了很多东西...但是我找不到如何解决此类问题的示例,或者我无法理解它=/
控制器(主要服务)
@Singleton
@Startup
public class Controller
private IEngine engine;
@PostConstruct
private void startup(int typeID)
Factory f = new Factory();
engine = f.getEngine(typeID)
工厂
public class Factory
@Produces
public IEngine getEngine(int typeID)
if(typeID==1)
return new EngineA();
else
return new EngineB();
多态的IEngine接口
public interface IEngine
void startUp();
这是一个EngineA的例子,EngineB是类似的
@Stateful
public class EngineA implements IEngine
@Inject
private CoinManager cm;
//@Override
public void startUp()
cm.doSomeThing();
不幸的是,即使工作正常,这也不允许我在 EngineA 中使用 @injection。事实上,EngineA 中的 cm 为空。我怎样才能让它发挥作用?
BR 和 THX! 斯蒂芬
【问题讨论】:
【参考方案1】:好吧,让我们退后一步看一下。
首先,不要自己调用生产者。让 CDI 完成这项工作,然后继续告诉它在哪里注入它。您的Controller
可能看起来像这样(但可能不会,您的帖子中有多个误解)。
@Singleton
@Startup
public class Controller
@Inject // just tell CDI to give you this
// it won't be this easy here, but it is just to give you an idea
private IEngine engine;
使用 CDI,您希望尽可能避免通过 new
创建实例。原因是,一旦您自己创建了一个实例,CDI 确实不可以控制创建,因此不能向其中注入任何东西!这就是您的null
的来源。
现在,如果您有制作人...
1) 必须放在一个 bean 类中(假设可以)
2) producer 方法的任何参数都必须是可注入的
3) 生产者通常通过new
创建实例,因此 CDI 无法注入任何东西。如果您需要,您可能需要研究另一种方法(生产者通常用于将非 CDI 对象转换为 bean,因此他们不需要注入生产的豆子中)。
您的生产者有一个参数int typeID
,这意味着 CDI 甚至可以通过此方法调用和实例化任何东西,它需要具有这种可注入性(对于 int,我想您需要另一个生产者)。或者,您可以将检索 typeID
的逻辑直接放在生产者方法中,而不是将其作为参数传递。
总而言之,您要采用的方法取决于您检索int typeID
的方式和时间,以及它是否可以在运行时更改。在任何情况下我建议您放弃生产者方法,而是将Instance<?>
与@Qualifier
结合使用。这应该为您提供足够的多功能性和动态分辨率。
【讨论】:
以上是关于在 JEE 中使用生产者和具有 CDI 的多态性添加有状态 bean的主要内容,如果未能解决你的问题,请参考以下文章
由于 CDI/Weld 中的 @Named,@ManagedBeans 在 JavaEE6 中过时了吗?