2011-01-20 102 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