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

Picocli应用中如何通过@Inject注入SeContainer/CDI实例本身?

无特定CDI实现依赖的Picocli工厂实现方案

问题核心原因

注入SeContainer失败是因为CDI规范并未将SeContainer定义为可直接注入的内置Bean——它是容器自身的实例,规范仅提供CDI.current()这一标准方式获取当前容器,而非依赖注入。

可行解决方案

方案1:基于CDI.current()的规范实现

在绝大多数CLI单容器场景下,CDI.current()是可靠的。若担心多容器场景,可通过@PostConstruct提前缓存容器实例,确保获取的是创建当前Bean的容器:

@ApplicationScoped
public class PicocliCDIFactory implements CommandLine.IFactory {
    private CDI<Object> cdi;

    @PostConstruct
    void init() {
        this.cdi = CDI.current();
    }

    @Override
    public <K> K create(Class<K> cls) throws Exception {
        return cdi.select(cls).get();
    }

    @PreDestroy
    void cleanup() {
        if (cdi != null) {
            cdi.close();
        }
    }
}
  • 用CDI<Object>替代具体容器类型,完全遵循CDI规范,无任何实现依赖。
  • 多容器场景下,@PostConstruct在容器内部线程执行,此时CDI.current()绑定的正是创建该工厂Bean的容器,可保证实例正确性。

方案2:通过Producer转为可注入Bean

若偏好依赖注入的代码风格,可自定义Producer将CDI实例转为可注入Bean:

@ApplicationScoped
public class CDIContainerProducer {
    @Produces
    @ApplicationScoped
    public CDI<Object> produceCDIContainer() {
        return CDI.current();
    }
}

修改工厂类实现注入:

@ApplicationScoped
public class PicocliCDIFactory implements CommandLine.IFactory {
    private final CDI<Object> cdi;

    @Inject
    public PicocliCDIFactory(CDI<Object> cdi) {
        this.cdi = cdi;
    }

    @Override
    public <K> K create(Class<K> cls) throws Exception {
        return cdi.select(cls).get();
    }
}

该方案本质仍基于CDI.current(),但通过Producer适配为依赖注入模式,保持实现中立性。

关键说明

  • CDI规范未定义SeContainer的注入支持,它是Jakarta EE SE容器的入口类,仅能通过SeContainerInitializer创建或CDI.current()获取。
  • CLI应用通常不会启动多容器,多容器场景只要保证工厂Bean部署与CDI.current()调用在同一容器上下文线程中,即可获取正确实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 02:21:09