2010-07-07 63 views
11

我想寫這一段代碼:注入靜態EJB,廢話?

@Stateless 
public class MyEjb 
{ 
    @EJB 
    private static MyOtherEjbWhichIWantStatic myOtherEjb; 
} 

這對我來說很有意義,我想注入一個EJB在我的課,作爲靜態元素,由於種種原因。

Java不是很滿意,不幸的是

com.sun.enterprise.container.common.spi.util.InjectionException: Illegal use of static field private static MyOtherEjbWhichIWantStatic myOtherEjb on class that only supports instance-based injection 

我不明白,爲什麼我不能注入靜態EJB到另一個EJB?

回答

26

正如其他人所指出的,這是不規範允許和短版就是@EJB註釋僅支持靜態成員的班級,main()功能(參見EJB 3.0規範和應用程序客戶端容器)。

爲什麼會這樣呢?首先,讀寫靜態字段在EJB中是完全禁止的(這是EJB限制的一部分)。從Why can't I use nonfinal static fields in my enterprise bean?

非最終靜態類字段中的EJB不允許的,因爲這些領域使企業Bean很難或不可能分發。靜態類字段在特定類的所有實例中共享,但僅在單個Java虛擬機(JVM)中共享。更新靜態類字段意味着要在該類的所有實例之間共享該字段的值。但是,如果一個類同時在多個JVM中運行,那麼只有那些與更新實例在同一個JVM中運行的實例才能訪問新值。換句話說,如果在單個JVM中運行,非最終靜態類字段的行爲將會不同,而不是在多個JVM中運行。 EJB容器保留了跨多個JVM(運行在同一臺服務器上或任何一個服務器集羣上)分發企業bean的選項。非最終的靜態類字段是不允許的,因爲企業bean實例將根據它們是否被分發而表現不同。

如果這些字段標記爲final,則使用靜態類字段是可以接受的做法。由於最終字段無法更新,因此企業bean的實例可以由容器分發,而不用擔心這些字段的值會變得不同步。

但是,雖然使用只讀靜態字段是允許的,但這不適用於EJB。無狀態EJB可能會被合併,容器可能會決定銷燬它們(這是特定於實現的),並且您想讓容器選擇要使用的實例,尤其是在分佈式環境中。換句話說,永遠不要假設你被綁定到一個特定的實例。

所以最後,是的,這是一個廢話。

+0

晶瑩剔透,謝謝! – 2010-07-07 15:21:31

0

從Java EE 5規範注入靜態EJB只允許在應用程序客戶端主類中使用。

對於除應用程序客戶端主類以外的所有類,字段或方法不能是靜態的。由於應用程序客戶端使用與J2SE應用程序相同的生命週期,因此應用程序客戶端容器不會創建應用程序客戶端主類的任何實例。相反,調用靜態main方法。爲了支持應用程序客戶端主類的注入,爲注入註釋的字段或方法必須是靜態的。

1

我不明白,爲什麼我不能注入 靜態EJB到另一個EJB?

由於the spec不允許它:

5.2.3Annotations和注射

如以下 段,某些 容器管理組件類的字段或方法描述 可能被註釋爲要求從應用程序組件的 環境中注入一個 條目int o 班。 [...] 對於除 應用程序客戶端主類之外的所有類, 字段或方法不得爲 靜態。

請注意,異常(應用程序客戶端主類)只存在,因爲這些類永遠不會實例化。基本上,靜態字段通常是有問題的,而且在應用程序服務器中也是如此,因爲它們可以繞開請求處理線程和事務的分離,這是首先使用應用程序服務器的關鍵。