如何向CDI @Dependent bean的实例化传递运行时参数?
如何为CDI中通过Instance.get()获取的@Dependent bean在实例化时传递运行时参数
CDI本身并不支持instance.get(name)这种直接传递构造参数的语法,但可以通过两种常用方式实现在实例化阶段传入运行时参数、创建不可变@Dependent bean的需求:
方法一:自定义限定符 + 生产者方法
通过自定义限定符传递运行时参数,配合生产者方法创建不可变实例:
1. 定义不可变的Person类
public class Person { private final String name; // 仅提供带参构造函数,确保实例不可变 public Person(String name) { this.name = name; } public String getName() { return name; } }
2. 创建自定义限定符
用限定符携带运行时参数:
@Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) public @interface NamedPerson { // 用@Nonbinding标记,避免CDI将参数作为bean匹配的固定条件 @Nonbinding String value(); }
3. 实现限定符的字面量类
用于在运行时动态创建限定符实例:
public class NamedPersonLiteral extends AnnotationLiteral<NamedPerson> implements NamedPerson { private final String name; public NamedPersonLiteral(String name) { this.name = name; } @Override public String value() { return name; } }
4. 编写生产者方法
通过生产者接收参数并创建不可变Person实例:
public class PersonProducer { @Produces @NamedPerson("") // 占位默认值,实际使用时会被动态覆盖 @Dependent public Person createNamedPerson(String name) { return new Person(name); } }
5. 使用方式
通过Instance.select()结合动态限定符获取实例:
@Inject @Any Instance<Person> personInstance; // 运行时传入参数 String name = "Some One"; Person person = personInstance.select(new NamedPersonLiteral(name)).get();
方法二:通过BeanManager编程式创建实例
直接使用CDI的BeanManager手动获取bean元数据,并传递构造参数创建实例:
@Inject BeanManager beanManager; public Person createPersonWithName(String name) { // 获取Person对应的Bean实例 Set<Bean<?>> beans = beanManager.getBeans(Person.class); Bean<Person> personBean = (Bean<Person>) beanManager.resolve(beans); // 创建CreationalContext CreationalContext<Person> ctx = beanManager.createCreationalContext(personBean); // 传递构造参数创建实例 return personBean.create(ctx, Collections.singletonList(name)); }
使用时直接调用该方法即可:
String name = "Some One"; Person person = createPersonWithName(name);
注意事项
- 两种方式都适用于@Dependent作用域的bean,因为@Dependent bean每次获取都会创建新实例,符合运行时参数的动态性需求
- 如果使用生产者方法,必须将限定符的
value()标记为@Nonbinding,否则CDI会将参数值作为bean匹配的固定条件,无法动态传递不同参数
内容的提问来源于stack exchange,提问作者Julio Faerman
相关产品推荐
相关产品推荐

