You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EE应用中EJB模块CDI事件@Inject注入失效原因排查

问题根源与解决方案

问题原因

你遇到的event为null的核心原因是:你手动使用new EventDispatcher()创建了EventDispatcher实例,这个实例不在CDI容器的管理范围内。CDI容器只会对它自己创建和管理的Bean实例执行依赖注入操作,手动实例化的对象不会触发任何CDI的注入逻辑,所以EventDispatcher里的@Inject Event<CcPayload>自然不会被填充,始终为null。

解决方案

1. 让CDI管理EventDispatcher的实例

修改DailyWork类,通过@Inject注入EventDispatcher,而不是手动new:

@Singleton
@Startup
public class DailyWork {
  static final Logger logger = LoggerFactory.getLogger(DailyWork.class);

  // 注入CDI管理的EventDispatcher实例
  @Inject
  private EventDispatcher eventDispatcher;

  @PostConstruct 
  public void automaticTimeout() {
       try {
           CcPayload payload = new CcPayload(cc.getId()+"","SOME PAYLOAD");
           eventDispatcher.fire(payload); // 使用注入的实例触发事件
       } 
       catch (Exception ex) {
           logger.warn("Cannot calculate Balance for CC "+cc);
       }
   }    
 }

因为DailyWork是@Singleton @Startup的EJB,本身属于CDI容器管理的Bean,所以可以直接注入其他CDI Bean(包括EventDispatcher)。

2. 简化实现:直接在EJB中注入Event

你完全可以省略EventDispatcher这个中间类,直接在DailyWork中注入Event<CcPayload>,代码更简洁:

@Singleton
@Startup
public class DailyWork {
  static final Logger logger = LoggerFactory.getLogger(DailyWork.class);

  @Inject
  private Event<CcPayload> ccEvent;

  @PostConstruct 
  public void automaticTimeout() {
       try {
           CcPayload payload = new CcPayload(cc.getId()+"","SOME PAYLOAD");
           ccEvent.fire(payload); // 直接触发事件
       } 
       catch (Exception ex) {
           logger.warn("Cannot calculate Balance for CC "+cc);
       }
   }    
 }

关键注意点

  • 你的EJB模块中beans.xml配置的bean-discovery-mode="all"是正确的,它会让CDI自动发现所有符合条件的Bean(包括EventDispatcher),不需要额外给EventDispatcher添加@Named或其他Bean定义注解。
  • 任何需要CDI依赖注入的对象,都必须由CDI容器创建(通过注入、Instance获取等方式),绝对不能用new手动实例化,否则注入逻辑不会生效。

内容的提问来源于stack exchange,提问作者KronosOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:45:09