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

