2012-11-29 117 views
5

我想我在這裏有一個基本的理解問題,我希望有人能向我解釋這一點。JAVA EE 6共享有狀態EJB之間的實例

假設我們有一個狀態EJB_A和狀態EJB_B和sessionscoped ManagedbeanA:

@Stateful 
@LocalBean 
public class EJB_A { 
} 

@Stateful 
@LocalBean 
public class EJB_B { 
    @EJB 
    EJB_A ejb; 
} 
@ManagedBean 
@SessionScoped 
public class ManagedBeanA { 
    @EJB 
    EJB_A ejb; 
} 

在ManagedBeanA,創建EJB_A。現在,當我使用具有EJB_A作爲屬性的EJB_B時,在EJB_B中創建了一個新的EJB_A實例。它不是在ManagedBeanA中創建的同一個EJB_A實例。

我不明白,因爲我認爲有狀態EJB的全部意義在於,對於每個客戶端,只有一個實例由EJB容器創建並共享和管理。有人可以向我解釋這個嗎?還請解釋我如何才能實現一個EJB的同一個實例被多個其他EJB共享?

謝謝

+0

「現在,當我使用EJB_B「你是什麼意思?你是如何驗證它不是同一個實例的? –

+0

當我投入EJB_B並查看EJB_A的屬性(例如字符串屬性)時,EJB_A bean的屬性與受管理bean所實例化的EJB_A的屬性不同。 – user1727072

+0

你在哪裏'instanciate'EJB_B;在另一個ManagedBean或Java客戶端(遠程查找)中? –

回答

9

是的,你混了不同的概念,不同的APIS太... 我寧願當你說使用@注入了@EJB並指定注入實例的範圍..

@Stateful 
@LocalBean 
public class EJB_A { 
} 

@Stateful 
@LocalBean 
public class EJB_B { 
    @Inject @SessionScoped 
    EJB_A ejb; 
} 
@ManagedBean 
@SessionScoped 
public class ManagedBeanA { 
    @Inject @SessionScoped 
    EJB_A ejb; 
} 
+0

你能解釋爲什麼我應該使用@Inject而不是@EJB? – user1727072

+1

那麼,這個主題的深入討論是: [鏈接] http://www.seamframework.org/107780.lace 基本上,判別因子是'@ Inject'總是知道的範圍注入的對象,並確保注入的實例是一個託管的實例(從而防止令人討厭的遠程bean序列化問題)。 使用@Inject獲得一個(有時是代理的)託管對象,使用'@ EJB'獲得一個資源,與簡單的JNDI查找沒多大區別 –

+0

謝謝你爲我解釋了很多:)! – user1727072

1

我想我混了兩件事情 - @SessionScoped和@Stateful。

@Stateful註釋並不意味着每個客戶端只創建一個實例。這僅僅意味着@ Stateful-EJB只屬於一個客戶端,而@ Stateless-EJB可以被多個客戶端共享。因此@ @ Stateful-EJB具有N:1關係(N @ Stateful-EJB屬於正好一個客戶端)和@ Stateless-EJB具有N:M關係(N @ Stateless-EJBS屬於M個客戶端)。這意味着,通過僅對@Stateful EJB使用@ EJB-Annotation,EJB-instance不能被多個其他EJB共享。

另一方面,似乎只有每個客戶端創建一次@ Sessionscoped-Managedbean。

我知道了嗎?

2

我剛剛做了一些閱讀here

的原因是,一個EJB 3.0有狀態會話Bean中創建一個新的 豆身份 遠程或本地業務接口的結果每個查找()。從查找返回的每個引用指的是不同的有狀態會話bean。由呼叫者決定 如何管理對該參考的訪問。通常,應用程序將在HttpSession或 應用程序範圍(ServletContext)作用域中存儲引用以供後續訪問。

和:

你的情況不要忘記我們正在處理2種類型的會話:在 會話bean和Web會議。前者確保一旦你請求一個有狀態bean,它的身份在該用戶會話中保持不變。但是當你使用後者時,你在bean會話頂部的 上有一個Web會話。爲了確保您從2個不同的JSP訪問同一個bean(或者當您重新加載時),您需要將 bean的標識存儲到Web會話作用域中。

所以你其實是對的。當您想要使用您的實例時,您必須使用ManagedBean將其檢索到其他位置,因爲EJB實例與此會話上下文關聯。因此,如果您想簡化它並確保每個會話只存在一次EJB,請使用CDI並另外使用@javax.enterprise.context.SessionScoped註釋EJB本身;比你可以確定。

+0

非常感謝您的幫助! – user1727072