這是可能的:是否可以在Java EE 6中將靜態變量注入CDI Bean?
@Inject
@MessageTransport(MessageTransportType.SMS)
public static MessageSender messageSender;
我得到當我試圖訪問這個靜態變量NPE。所以我想知道,如果這是不可能的一般。
在此先感謝。
這是可能的:是否可以在Java EE 6中將靜態變量注入CDI Bean?
@Inject
@MessageTransport(MessageTransportType.SMS)
public static MessageSender messageSender;
我得到當我試圖訪問這個靜態變量NPE。所以我想知道,如果這是不可能的一般。
在此先感謝。
不是一般做是因爲一個靜態變量不能有一個範圍,即它只是一個全班(閱讀應用程序),因此它沒有任何意義,因爲每個實例都將嘗試將其設置爲基於一個新的價值在當前範圍內。
這是不可能當前,但它在理論上是不可能的。
對方回答表明,這是不可能的,但解釋說明注射的方式縫2的工作,我會嘗試從內存形容它。一些僞代碼:
@Name("a")
class A() {
@In
B b;
void something() {
b.doTheThing();
}
}
Seam 2支持通過BijectionInterceptor注入。爲了讓攔截器工作,Seam創建了組件的代理實例。在這裏,當a.something
方法被調用時,它會被截取,並且proxified b
實例確實會就在a
的實例字段b
注入。如果B
駐留的上下文在該時刻未處於活動狀態,則注入將失敗,並且a.something
方法調用也會失敗。
現在讓我們看看類似的例子爲CDI:
class A() {
@Inject
B b;
void something() {
b.doTheThing();
}
}
在CDI仍有代理。但注射的方式不同。 CDI引入了上下文引用的概念。這是存儲在a.b
字段中的內容。當a.something
被稱爲沒有什麼有趣的事情發生。在任何情況下都不可能有B
實例,並且a.something
方法仍然會被調用。但是當涉及到調用b.doTheThing
方法時 - 那是CDI開始尋找實際B
實例的時候。例如,有可能獲得ContextNotActiveException
。
因此,這似乎是可能的。我發現some interesting notes在老焊接部位,這可能,爲什麼這還沒有實現解釋:
靜態注射
注射靜態成員有幾個問題:
- 一個類可以多個應用程序之間共享,以及Java EE規範沒有定義該規則。
- 在Java EE外部,很難準確定義何時注入靜態成員。
不過,也有這幾大usecases的:
- 記錄器注入,
- 注射實體類和
- 注入與鈍化範圍的對象。
所以我們確實需要在這裏支持一些東西。也許這將是不夠的說:bean的第一個實例進行實例化之前
- 無靜電注射共享庫,並
- 靜態字段注入(但隨後靜態注入將不支持對非 - 大豆類)。
有專用於靜態注射開放CDI問題:CDI-51。
這是一個非常好的答案。只是想踢你另一個原因,你可能想這樣做。如果您正在遷移遺留應用程序,則可以使用靜態注入來幫助緩解從靜態過渡到DI的痛苦。 –
斯圖爾特道格拉斯關於CDI注射方法的文章:https://developer.jboss.org/blogs/stuartdouglas/2010/10/12/weld-cdi-and-proxies –
很明顯,你不應該這樣做,但有時候我想你必須做,因爲有時候有些對象實例化了一些對象(例如使用ServiceLoader
),並且你想注入它們。這裏有一個你可以做的破解:
class StaticallyInjected {
private static MyBean bean;
void inject (@Observes @Initialized (ApplicationScoped.class) Object x,
MyBean bean) {
StaticallyInjected.bean = bean;
}
}
什麼是'對象x'在這裏做什麼? –
我從來不屑於查看實際類型。這個想法是搭載到應用程序範圍初始化上,這是註釋的作用。我猜這是代表你的應用程序的某種對象,可能取決於CDI的實現 –
我以爲我自己,感謝claryfing那。 – VWeber