@EJB注入与查找 - 性能问题

时间:2011-01-20 22:34:59

标签: performance ejb-3.0 lookup code-injection service-locator

我在使用@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个ejbs(myBean1及其19个依赖项)

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

假设在大多数情况下,我们将仅对myBean1的每个业务方法使用单个依赖项。因此,每次我们想要注入该bean时,我们都会强制容器保留许多不需要的EJB。让我们假设我们正在对远程bean进行操作,因此容器在注入依赖bean之前可能还需要执行一些负载平衡算法。

问题:

  1. 在群集环境中运行时,这是否会导致不必要的资源预留和更多性能问题?

  2. 也许好的旧ServiceLocator可能是更好的解决方案,因为使用这种方法我们会在需要时询问特定的EJB吗?

2 个答案:

答案 0 :(得分:12)

容器不会注入EJB的实例;它注入一个轻量级容器生成的代理对象的实例,该对象实现了所需的接口。

public class MyBean1 implements MyBean1Remote {
   ...
}

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

在您的示例中,MyAnotherBean.myBean1将注入一个实现MyBean1Remote接口的代理对象。

假设一个无状态会话bean(因为你提到了池),容器不会从方法就绪池中分配一个实际的EJB实例,直到在代理上调用一个方法,并且实例是在代理方法调用返回之前返回到池。

答案 1 :(得分:5)

在大多数情况下,特别是在使用无状态会话bean时,您的bean实例将被池化。池化背后的基本原理之一是依赖注入查找可能相对昂贵,因此bean与汇集了(存根)已经注入的所有依赖项

因此,每次在MyAnotherBean上调用方法时,都不会创建具有20个传递依赖项的Bean,并且所有这些依赖项都是动态解析的。相反,从池中选择完全实例化的实例,并将方法调用定向到该实例。

另请注意,除非您正在进行JNDI联合,否则通常无法轻松注入远程EJB。