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

如何在CDI中创建由注入类传递参数的Bean?

嘿,这个问题我之前在项目里也折腾过!CDI 默认的 @Inject 确实没法直接在注入点传参数,但有几种很实用的方案能实现你要的需求,我给你一步步拆解:

方案1:用 Qualifier + Producer 方法(编译时固定参数)

如果你的参数是预先确定好的,这种方式最符合 CDI 的规范。

首先给 MyBean 加个带参数的构造函数:

public class MyBean {
    private final int param1;
    private final int param2;

    // 接收参数的构造函数
    public MyBean(int param1, int param2) {
        this.param1 = param1;
        this.param2 = param2;
    }

    // 使用参数的示例方法
    public void printParams() {
        System.out.println("参数1: " + param1 + ", 参数2: " + param2);
    }
}

然后定义一个自定义的 Qualifier 注解,用来携带参数:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface MyBeanParams {
    int param1();
    int param2();
}

接下来写一个 Producer 类,负责根据 Qualifier 里的参数创建 MyBean 实例:

public class MyBeanProducer {
    @Produces
    @MyBeanParams(param1 = 0, param2 = 0) // 这里是默认值,会被注入点的参数覆盖
    public MyBean produceMyBean(InjectionPoint injectionPoint) {
        // 从注入点获取我们定义的参数注解
        MyBeanParams params = injectionPoint.getAnnotated().getAnnotation(MyBeanParams.class);
        return new MyBean(params.param1(), params.param2());
    }
}

最后在注入类里,通过 Qualifier 指定参数:

@Dependent
public class MyInjectingClass {
    @Inject
    @MyBeanParams(param1 = 10, param2 = 20) // 在这里传入你需要的参数
    private MyBean myBean;

    public void useBean() {
        myBean.printParams(); // 会输出:参数1: 10, 参数2: 20
    }
}
方案2:用 CDI Instance API(运行时动态传参)

如果你的参数是运行时动态生成的(比如从用户输入、数据库读取),这个方案更合适。

MyBean 还是用带参数的构造函数,然后在注入类里注入 Instance<MyBean>,手动创建实例:

@Dependent
public class MyInjectingClass {
    @Inject
    private Instance<MyBean> myBeanInstance;

    public void useDynamicParams() {
        // 模拟运行时获取的动态参数
        int dynamicParam1 = 50;
        int dynamicParam2 = 60;

        // 传递构造参数创建实例
        MyBean myBean = myBeanInstance.select().get(dynamicParam1, dynamicParam2);
        try {
            myBean.printParams(); // 输出:参数1: 50, 参数2: 60
        } finally {
            // 手动创建的 @Dependent 作用域 Bean 需要手动销毁
            myBeanInstance.destroy(myBean);
        }
    }
}

注意:这里 MyBean 的作用域最好设为 @Dependent,因为手动创建的实例需要我们自己管理生命周期,销毁时调用 destroy 能确保CDI清理相关资源。

方案3:用工厂类(简单直接)

如果不需要复杂的 CDI 生命周期管理,直接用工厂类也是个省心的选择。

先写一个被 CDI 管理的工厂类:

@Dependent
public class MyBeanFactory {
    public MyBean createMyBean(int param1, int param2) {
        return new MyBean(param1, param2);
    }
}

然后在注入类里注入工厂,调用方法创建实例:

@Dependent
public class MyInjectingClass {
    @Inject
    private MyBeanFactory myBeanFactory;

    public void useBean() {
        int param1 = 30;
        int param2 = 40;
        MyBean myBean = myBeanFactory.createMyBean(param1, param2);
        myBean.printParams(); // 输出:参数1: 30, 参数2: 40
    }
}

这种方式最简单,但缺点是工厂创建的 MyBean 实例不会被 CDI 容器管理(除非结合 Producer 方法),所以如果 MyBean 里需要注入其他 CDI Bean,这个方案就不适用了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:02:57