2013-02-25 22 views
11

假設我有一個Car類。在我的代碼中,我想創建10輛汽車。 Car類有一些@Inject註釋的依賴關係。什麼是最好的方法來做到這一點?如何在CDI上實時創建實例

CDI有,我可以用它來創建一個汽車提供者接口:

@Inject Provider<Car> carProvider; 
public void businessMethod(){ 
    Car car = carProvider.get(); 
} 

不幸的是,不工作,如果我沒有說有@Produces註釋的方法,它創建了一個CarFactory汽車。儘管它反映了現實世界中我無法在沒有工廠的情況下創造汽車,但我寧願不寫任何事情的工廠。我只想讓CDI容器像其他任何bean一樣創建我的汽車。你如何建議我製作這些汽車?

回答

8

改爲使用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 ... 
    } 

} 
+0

這實際上是我最終使用的。你能否修正你的例子,構造函數參數與類屬性不是同一類型:Car vs UIModule。 另外我認爲注射應該是@New而不是@Any的annotetade。對於use()方法來說,一個更好的例子就是顯示你如何得到Car的一個實例。例如'carInstances.get()' – palto 2015-01-08 13:11:03

+0

@New在CDI 1.1中被棄用,優先於@Dependent bean。參見CDI 1.1,第3.14節。我不明白使用提供者有什麼問題,我。即CDI.current()。select(Car.class).get()'? – 2015-01-26 16:13:43

+0

@MartinAndersson最初的問題是我必須創建一個使用提供者的工廠。你在評論中提供的例子對我來說是全新的。也許你可以從中創建一個答案? – palto 2015-01-27 07:17:53

2

你可以使用預選賽與@Produces註解:

@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; 
+0

'@New在CDI 1.1中被棄用,優先於@Dependent bean。參見CDI 1.1,第3.14節。 – 2015-01-26 16:14:24

+0

@MartinAndersson我知道,但由於CDI 1.1的答案時間還沒有出來,所以答案是去CDI 1.0(這裏只是爲了澄清這一點) – FibreFoX 2015-01-27 09:04:21

0

另一種方式來做到這將是簡單地不給汽車任何CDI範圍,這使得它依賴,你會得到一個新的實例,每次注入和噸在包含的實例被銷燬之前,軟管實例不會被銷燬。

+0

範圍是不值得擔心的,就我而言可以理解的是,他希望有一個注入生產者,而不必實施特定的生產者階級。你說得對,所有注入的cdi-beans變成了「@依賴」,但它不是什麼palto在談論 – FibreFoX 2013-02-27 19:37:21

+0

「每次注入新實例」?一個依賴者如何注射「每次」?注射只發生一次。代理人。如果一個@Dependent bean或代理被注入,那麼對這個代理的每個調用將總是被路由到同一個支持bean。 – 2015-03-07 09:59:32

+0

它會注入代理一次,是的,但是如果該代理解析爲一個依賴的作用域bean,那麼該依賴的作用域bean將在請求注入的每個新bean實例上創建。注入的bean變得依賴於其他生命週期。 – LightGuard 2015-03-07 16:13:52

5

我對程序查找最喜愛的模型是使用CDI.current().select().get()

演示here

的servlet有兩個CDI豆的依賴,一個請求範圍,而另一個應用程序作用域:

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

private final ApplicationScopedBean applicationScoped 
      = CDI.current().select(ApplicationScopedBean.class).get(); 

使用這個servlet測試類可以發現here

檢查代碼,您會注意到代碼與您將使用的代碼@Inject MyBean myBean;完全相同。