2013-10-22 80 views
4

我正在使用緩存javax.naming.Context#lookup調用結果的服務定位器實現,並將其映射到所請求的EJB接口,因此所有後續請求(對於同一個EJB)在第一個請求之後返回緩存實例。帶緩存的EJB服務定位器

我的擔憂是:

  1. 由於相同的情況下被使用,不存在 服務器EJB池這將成爲多個同時發生的請求 與多個EJB(除非底層服務器的邏輯不知何故使得利用 使用EJB池的)
  2. 無狀態和有狀態EJB是線程安全的,但由於再次使用 只有每個EJB類一個實例,EJB擁有的EntityManager 通過@PersistenceContext注入,我認爲MEA NS多個 線程可以使用相同的EntityManager實例(不僅僅是 持久化上下文),這絕對不是線程安全的

你認爲這是最好不要在服務定位器使用緩存,或我的擔心對EJB行爲是不合理的?

回答

5

從查找操作(通過JNDI服務)得到的是一個名爲Stub的對象,並且他沒有固定任何特殊的EJB實例。

一旦緩存,每次調用EJB服務時,存根可以從池中選擇一個不同的EJB實例(這適用於無狀態);即使在集羣環境中,存根對象也能夠從不同的服務器中選擇一個EJB實例。

因此,緩存存根對象應該不成問題。

請注意,我在談論無狀態,我認爲緩存對有狀態會話bean沒有意義。

EJB查找是一個耗時的操作,所以緩存提高了客戶端的性能。


關於您的評論:

如果您正在使用的EntityManager所使用的多個併發線程就像一個Servlet一個組件內,是的,你將不得不關心併發,但EJB的胎面模型暗示這不會是多個線程同時使用同一個EntityManager實例,所以EM不是線程安全的事實並不重要。

我關注的仍然是,不同的EJB使用 相同注射(通過@PersistenceContext)EntityManager實例

我認爲,簡單的風景最好的方式來想想,如果如描述here

在多用戶的客戶機/服務器應用程序的最常見的模式是 EntityManager的每次請求。在這個模型中,來自客戶端的請求是 發送到服務器(JPA持久層運行的地方),一個新的 EntityManager被打開,並且所有的數據庫操作都在 這個工作單元中執行。一旦工作完成(並且已準備好客戶端的響應 ),持久性上下文將被刷新爲 並關閉,以及實體管理器對象。

這將更加難以遏制;)

+0

我已經證實了這一點,使用在相同的緩存實例與並行方法調用的測試 - 儘管參考EJB(存根如你所說)是一樣的,調試確認實際的EJB是不同的。我關心的仍然是不同的EJB使用相同的注入(通過@PersistenceContext)EntityManager實例。我無法確認100%這是線程安全的(因爲EntityManager本身不是線程安全的),但似乎合乎邏輯的是,由於它是容器管理的,它是 - 並且可能使用代理對象的相同原理來真正的新興市場。 – alterfox