2011-01-20 43 views
5

我在使用@EJB註釋時遇到了與可能的性能問題相關的問題。想象一下下面的場景@EJB注入與查找 - 性能問題

public class MyBean1 implements MyBean1Remote{ 
@EJB 
private MyBean2Remote myBean2; 
@EJB 
private MyBean2Remote myBean3; 
... 
@EJB 
private MyBean20Remote myBean20; 
} 

有一個bean有許多依賴到其他bean。根據EJB規範,如果我想將MyBean1Remote注入到其他bean中,容器將不得不從其池中注入所需的所有依賴項,並將其注入到MyBean1Remote中,然後將引用注入MyBean1Remote存根。

所以在下面的情形容器需要保留20層的EJB(myBean1及其19依賴性)

public class MyAnotherBean implement MyAnotherRemote{ 
    @EJB 
    private MyBean1Remote myBean1 
} 

讓說,在大多數情況下,我們將利用每myBean1的每個業務方法只有單一的依賴。因此,每次我們要注入該bean時,都會強制容器保留許多不必要的EJB。讓我們也假設我們正在遠程bean上運行,因此在注入依賴bean之前,容器可能還需要執行一些負載平衡算法。

問題:

  1. 會不會在集羣環境中進行操作,而造成不必要的資源預留,更在性能問題?

  2. 也許好的舊ServiceLocator可能是更好的解決方案,因爲採用這種方法時,我們會在真正需要時請求特定的EJB?

回答

5

在大多數情況下,尤其是使用無狀態會話bean時,您的bean實例將被合併。合併背後的一個基本原理是依賴注入查找可能相對昂貴,因此該bean被合併爲,其所有依賴關係已被注入(存根)

因此,每當您調用MyAnotherBean上的方法時,都會創建具有20個傳遞依賴項的此bean,並且不會動態解析所有這些依賴項。相反,從池中選擇一個完全實例化的實例,方法調用將指向該實例。

另請注意,除非您正在執行JNDI聯合,否則通常無法輕鬆注入遠程EJB。

12

容器不注入EJB的實例;它會注入一個實現所需接口的輕量級容器生成代理對象的實例。

public class MyBean1 implements MyBean1Remote { 
    ... 
} 

public class MyAnotherBean implement MyAnotherRemote { 
    @EJB 
    private MyBean1Remote myBean1; 
} 

在您的示例中,MyAnotherBean.myBean1將注入一個實現MyBean1Remote接口的代理對象。

假設無狀態會話Bean(因爲您提到池),容器不會從方法就緒池中分配實際的EJB實例,直到在代理上調用方法,並且實例返回到池在代理方法調用返回之前。

+0

+1是的,這也是一個很好的答案:)實例本身從未被注入,但代理是。接下來,就像我的回答一樣,池中的實際實例已經解決了所有的依賴關係。 – 2011-01-22 11:27:33