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

如何向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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 02:05:32