2009-03-06 88 views
11

我們都知道,在Web層中,只有一個給定Servlet的實例存在服務多個請求的可能性。這可能會導致實例變量中的線程問題。將EJB作爲實例變量注入servlet是否安全?

我的問題是,使用@EJB註釋將EJB作爲實例變量注入servlet是否安全?

假設EJB的同一個實例將同時服務多個請求,我的初始本能是否定的。這似乎也是一些其他程序員的直覺:Don't inject to servlets

但是,我已經跳到了錯誤的結論。顯然,注入到servlet中的是代理,實際上容器是否爲每個請求提供了不同的實例並維護線程安全?因爲這個論壇會建議:Do inject to servlets

似乎有很多矛盾的意見。哪個是對的???

回答

3

您的參考「不要注入到servlet」中沒有提到任何有關ejbs或@ejb註釋的內容。它講述的不是線程安全的對象,比如PersistenceContext。

根據EJB規範,您可以從各種遠程客戶端(包括servlet(EJB 3.0規範(JSR-220) - 第3.1節)訪問ejbs。使用@EJB註釋注入ejb是一種通過依賴注入獲取EJB接口的方法(第3.4.1節),它可以替代在JNDI命名空間中查找ejb對象。因此,對於獲得的EJB,@EJB註釋沒有什麼特別之處。

因此,基於EJB 3.0規範,使用@EJB註釋從servlet獲取ejbs是一種標準做法。

+0

這個答案在目前爲止是正確的,但並沒有解決OP的線程安全問題。我相信推薦設計的答案應該是正確的。 – 2010-05-05 20:28:59

+0

我想用@Inject(CDI,JEE 6)注入的EJB將會同樣安全,不是嗎? – marcus 2012-11-22 17:00:15

0

我認爲簡單的答案是,你不能保證它是安全的。

其原因是EJB規範中沒有任何明確規定EJB主接口必須是線程安全的。該規範僅概述了服務器端部分的行爲。你可能會發現,客戶端骨架實際上是線程安全的,但你需要看看它們是如何被你正在使用的庫實現的。註釋部分將擴展到一個服務定位器,這樣就不會爲你購買任何東西。

11

只要EJB是無狀態的,將Servlet中的EJB注入Servlet實例變量是安全的。你絕不能在Servlet中注入一個Stateful Bean。

您必須實現您的EJB無狀態,因爲它不包含任何實例變量,它本身保存有狀態值(如持久性上下文)。如果您需要使用持久化上下文,那麼您必須在EJB的方法中獲得它的一個實例。您可以通過將PersistenceContextFactory作爲EJB實例變量來實現,然後在EJB的方法中從Factory獲得實體管理器的實例。

PersistenceContextFactory是線程安全的,因此它可以注入一個實例變量中。

只要你符合上面所說的規則,它應該是線程安全的,在Servlet

1

這是一個喜憂參半注入無狀態Bean。

無狀態會話bean可能被注入並且是安全的。這是因爲即使使用了存根的單個實例,對該方法的訪問也將被容器序列化。

我認爲什麼推斷設計說是不是真的。無狀態會話bean是否使用持久性上下文無關緊要。只有一個調用者會同時訪問單個bean實例,因此即使持久化上下文不是線程安全的,EJB也會防止對其進行多次訪問。可以認爲它就好像每個會話bean方法都應用了synchronized關鍵字一樣。

在Servlet中注入EJB的主要問題我認爲是性能。當多個請求在等待爲它們執行會話bean方法時排隊等待時,單個存根實例將成爲爭用的主要區域。