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
相关产品推荐
相关产品推荐

