Java 如何在CDI中动态创建实例

Java 如何在CDI中动态创建实例,java,java-ee-6,cdi,Java,Java Ee 6,Cdi,让我们假设我有一个汽车类。在我的代码中,我想创建10辆汽车。Car类有一些@Inject注释的依赖项。这样做的最佳方法是什么 CDI有一个提供程序接口,我可以使用该接口创建汽车: @Inject Provider<Car> carProvider; public void businessMethod(){ Car car = carProvider.get(); } @injectprovider-carProvider; 公共方法(){ Car Car=carProvi

让我们假设我有一个汽车类。在我的代码中,我想创建10辆汽车。Car类有一些@Inject注释的依赖项。这样做的最佳方法是什么

CDI有一个提供程序接口,我可以使用该接口创建汽车:

@Inject Provider<Car> carProvider;
public void businessMethod(){
    Car car = carProvider.get();
}
@injectprovider-carProvider;
公共方法(){
Car Car=carProvider.get();
}

不幸的是,如果我没有一个CarFactory,它有一个@products注释的方法来创建汽车,那么这就行不通了。它反映了一个现实世界,没有工厂我无法生产汽车,但我宁愿不为所有东西写工厂。我只希望CDI容器像其他bean一样创建我的汽车。您建议我如何创建这些汽车?

您可以在@products注释中使用限定符:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
public @interface MyCars {
}
样品生产商方法:

@Produces
@MyCars
public Car getNewCar(@New Car car){
    return car;
}
用法:

@Inject
@MyCars
private Provider<Car> carProvider;
@Inject
@我的车
私人提供商carProvider;

另一种方法是简单地不给Car任何CDI作用域,这会使它依赖,并且每次注入时都会得到一个新实例,这些实例在包含实例被销毁之前不会被销毁。

只需使用javax.enterprise.inject.instance接口即可

像这样:

public class Bean {

    private Instance<Car> carInstances;

    @Inject
    Bean(@Any Instance<Car> carInstances){
        this.carInstances = carInstances;
    }

    public void use(){
        Car newCar = carInstances.get();
        // Do stuff with car ...
    }

}
公共类Bean{
私人机构;
@注入
Bean(@Any实例carInstances){
this.carInstances=carInstances;
}
公共用途(){
Car newCar=carInstances.get();
//用汽车做东西。。。
}
}

我最喜欢的编程查找模式是使用
CDI.current().select().get()

演示

servlet依赖于两个CDI bean,一个请求作用域,另一个应用程序作用域:

private final RequestScopedBean requestScoped
            = CDI.current().select(RequestScopedBean.class).get();

private final ApplicationScopedBean applicationScoped
            = CDI.current().select(ApplicationScopedBean.class).get();
可以找到使用此servlet的测试类


检查代码,您会发现代码与使用
@injectmybean-MyBean获得的代码完全相同

范围不需要担心,据我所知,他希望有一个注入生产者,而不必实现特定的生产者类。您是对的,所有注入的CDIBean都成为依赖的,但这不是palto所说的“每次注入一个新实例”吗?如何“每次”注入依赖者?注射只发生一次。代理权。如果注入了@Dependent bean或代理,那么对该代理的每次调用将始终路由到同一个支持bean。它注入代理一次,是的,但如果该代理解析为依赖作用域bean,则该依赖作用域bean将在请求注入的每个bean的新实例上新建。注入的bean依赖于其他bean的生命周期。这就是我最终使用的。您能否修复您的示例,构造函数参数与class属性的类型不同:Car vs UIModule。另外,我认为注射剂应该用@New而不是@Any注释。对于use()-方法,一个更好的例子是展示如何获得汽车实例。例如,
carInstances.get()
@New在CDI 1.1中被弃用,优先于@Dependent bean。见CDI 1.1,第3.14节。我真的不明白使用提供者有什么问题,我。e、 ,
CDI.current().select(Car.class).get()
?@MartinAndersson最初的问题是我必须创建一个工厂来使用提供者。你在评论中提供的例子对我来说是全新的。也许你可以从中创建一个答案?“@New在CDI 1.1中被弃用,而优先于@Dependent bean。参见CDI 1.1,第3.14节。@MartinAndersson我知道,但由于回答CDI 1.1的时间尚未结束,因此答案转到CDI 1.0(仅在此处澄清)