什么是EJB,它有什么作用?


151

试图了解什么是EJBbean,这意味着它们的实例是在一个池中管理的,等等。真的无法很好地抓住他们。

您能否解释一下它们的真正含义(实际上对于Java程序员而言)?他们在做什么?他们的目的是什么?为什么真正使用它们?(为什么不坚持POJO?)也许是一个示例应用程序?

请仅参考更新的信息EJB 3.1。有关EJB的过时信息可能会引起误解。

对于EJB学习初学者,请注意:

EJB基于分布式对象,这是指在通过网络链接的多台计算机(虚拟或物理)上运行的软件。


Answers:


161

为什么真正使用它们?(为什么不只坚持POJO?)

如果您需要访问数据库或访问其他连接性/目录资源的组件,或者需要从多个客户端访问的组件,或者旨在用作SOA服务的组件,那么当今的EJB通常“更大,更强大,更快(或至少更具可伸缩性)”并且比POJO更简单。对于通过Web或公司网络为大量用户提供服务而言,它们最有价值,而对于部门中的小型应用程序而言,它们的价值则相对较小。

  1. 通过松散耦合在多个应用程序/客户端之间重用/共享逻辑。
    EJB可以打包在自己的jar中,可以在很多地方部署和调用。它们是常见的组件。没错,POJO可以(小心地)设计为库,也可以打包为jar。但是EJB支持本地和远程网络访问-包括通过本地Java接口,透明RMI,JMS异步消息和SOAP / REST Web服务,从而避免了通过剪切(粘贴)jar依赖项与多个(不一致的)部署进行交互。
    它们对于创建SOA服务非常有用。当用于本地访问时,它们是POJO(添加了免费的容器服务)。设计一个单独的EJB层的行为为最大程度地提高封装,松散的耦合和内聚力提供了额外的注意,并促进了干净的接口(Facade),使调用者免受复杂的处理和数据模型的侵害。

  2. 可伸缩性和可靠性如果您应用来自各种调用消息/进程/线程的大量请求,它们将首先分布在池中的可用EJB实例中,然后排队。这意味着,如果每秒传入的请求数量大于服务器可以处理的数量,我们就会正常降级-始终有一些请求得到有效处理,多余的请求将等待。我们没有达到服务器“崩溃”的状态-所有请求同时经历可怕的响应时间,此外,服务器尝试访问的资源超出了硬件和OS可以处理的范围,从而导致崩溃。EJB可以部署在可以集群的单独层上-通过从一台服务器到另一台服务器的故障转移,可以提供可靠性,并且可以添加硬件以进行线性扩展。

  3. 并发管理。容器确保EJB实例由多个客户端自动安全地(串行地)访问。容器管理EJB池,线程池,调用队列,并自动执行方法级的写锁定(默认)或读锁定(通过@Lock(READ))。这样可以防止数据因并发的写冲突而损坏,并通过防止读写冲突来帮助一致地读取数据。
    这对于@Singleton会话Bean尤其有用,在该会话Bean中,该Bean在多个客户端调用者之间操纵和共享公共状态。可以轻松地覆盖它,以手动配置或以编程方式控制并发代码执行和数据访问的高级方案。

  4. 自动化交易处理。
    什么也不做,所有的EJB方法都在JTA事务中运行。如果使用JPA或JDBC访问数据库,则该数据库将自动加入事务中。对于JMS和JCA调用相同。在方法之前指定@TransactionAttribute(someTransactionMode),以指定该特定方法是否/如何参与JTA事务,从而覆盖默认模式:“必需”。

  5. 通过注入非常简单的资源/依赖关系访问。
    容器将查找资源并将资源引用设置为EJB中的实例字段:例如JNDI存储的JDBC连接,JMS连接/主题/队列,其他EJB,JTA事务,JPA实体管理器持久性上下文,JPA实体管理器工厂持久性单元,以及JCA适配器资源。例如,设置对另一个EJB,JTA事务,JPA实体管理器,JMS连接工厂和队列的引用:

    @Stateless
    public class MyAccountsBean {
    
        @EJB SomeOtherBeanClass someOtherBean;
        @Resource UserTransaction jtaTx;
        @PersistenceContext(unitName="AccountsPU") EntityManager em;
        @Resource QueueConnectionFactory accountsJMSfactory;
        @Resource Queue accountPaymentDestinationQueue;
    
        public List<Account> processAccounts(DepartmentId id) {
            // Use all of above instance variables with no additional setup.
            // They automatically partake in a (server coordinated) JTA transaction
        }
    }
    

    Servlet可以通过简单地声明一个实例变量来在本地调用此bean:

    @EJB MyAccountsBean accountsBean;    
    

    然后根据需要调用其方法。

  6. 与JPA的智能交互。默认情况下,按上述方式注入的EntityManager使用事务范围的持久性上下文。这对于无状态会话bean是完美的。当调用(无状态)EJB方法时,将在新事务中创建新的持久性上下文,所有检索/写入数据库的实体对象实例仅在该方法调用内可见,并且与其他方法隔离。但是,如果该方法调用了其他无状态EJB,则容器将传播并共享相同的PC给它们,因此相同的实体将通过PC在同一事务中以一致的方式自动共享。
    如果声明了@Stateful会话Bean,则通过将entityManager声明为扩展范围之一来实现与JPA的同等的智能亲和力:@PersistentContent(unitName =“ AccountsPU,type = EXTENDED)。跨多个bean调用和事务,缓存先前检索/写入的DB实体的内存中副本,因此无需重新检索它们。

  7. 生命周期管理。EJB的生命周期是容器管理的。根据需要,它可以创建EJB实例,清除和初始化有状态会话bean状态,钝化和激活并调用生命周期回调方法,因此EJB代码可以参与生命周期操作以获取和释放资源,或执行其他初始化和关闭行为。它还捕获所有异常,记录它们,根据需要回滚事务,并根据需要引发新的EJB异常或@ApplicationExceptions。

  8. 安全管理。可以通过简单的注释或XML设置来配置对EJB的基于角色的访问控制。服务器自动将经过身份验证的用户详细信息以及每个调用作为安全上下文(调用主体和角色)传递。它确保自动执行所有RBAC规则,以防止错误的角色非法调用方法。它允许EJB轻松访问用户/角色详细信息,以进行额外的编程检查。它允许以标准方式将额外的安全处理(甚至IAM工具)插入容器。

  9. 标准化和可移植性。EJB实现符合Java EE标准和编码约定,从而提高了质量,并易于理解和维护。通过确保代码都支持相同的标准功能和行为,并阻止开发人员意外采用专有的
    非便携式供应商功能,它还促进了代码向新的供应商应用服务器的可移植性。

  10. 真正的踢球者:简单。以上所有步骤都可以通过非常简化的代码来完成-使用Java EE 6中EJB的默认设置,或添加一些注释。在自己的POJO编码企业/工业强度的特点是方式更volumous,复杂且容易出错。一旦开始使用EJB进行编码,它们就很容易开发,并提供了许多“免费乘车”的好处。

在10年前的原始EJB规范中,EJB是一个主要的生产力难题。它们were肿,需要大量代码和配置构件,并提供了上述收益的约2/3。大多数Web项目实际上并未使用它们。但是,经过10年的调整,大修,功能增强和开发流程调整,这已发生了显着变化。在Java EE 6中,它们提供了最高水平的工业强度和使用简便性。

不喜欢什么?:-) :-)


67

EJB是Java组件,包含业务逻辑,您可以将其部署在容器中,并且借助注释,通常可以以声明性的方式从容器提供的技术服务中受益:

  • 事务管理:可以在调用EJB方法之前自动启动事务,并在该方法返回后进行提交或回滚。该事务上下文被传播到对其他EJB的调用。
  • 安全管理:可以检查调用方是否具有执行该方法所需的角色。
  • 依赖项注入:其他EJB或资源(例如JPA实体管理器,JDBC数据源等)可以注入到EJB中。
  • 并发性:容器确保一次仅一个线程调用EJB实例的方法。
  • 分布:可以从另一个JVM远程调用某些EJB。
  • 故障转移和负载平衡:EJB的远程客户端可以在必要时自动将其调用重定向到另一台服务器。
  • 资源管理:有状态的Bean可以自动钝化到磁盘,以限制服务器的内存消耗。
  • ...我可能已经忘记了一些要点。

当您提到交易时,您指的是持久性?
jacktrades 2012年

6
是的,但不仅如此。EJB容器提供了分布式JTA事务管理器,在单个事务中支持多个资源。例如,您可以在一个事务中更新数据库中的某些数据,并发送一些JMS消息。如果发生任何故障,则将回滚所有内容:数据库更新和发送的消息。
JB Nizet 2012年

@JBNizet对不起我在旧线程上发表评论,但是像Spring这样的EJB框架并没有提供您提到的这些服务。我不明白其中的区别
MoienGK

基本原理是相同的。Spring借鉴了EJB的想法,反之亦然。但是API,实现,部署方式和某些功能有所不同。
JB Nizet

@JB Nizet在MVC模式中,一般将EJB放在哪里?我会说它们属于模型层,尽管我认识很多人说他们是控制器。如果EJB包含业务逻辑(您说过的话),那么它们就是按定义建模的层。
user107986 2015年

22

希望Oracle文档中的内容能够帮助像我这样的人以一种简单的方式理解EJB的主题。

什么是企业Bean?企业Bean用Java编程语言编写,是一种服务器端组件,封装了应用程序的业务逻辑。业务逻辑是满足应用程序目的的代码。例如,在库存控制应用程序中,企业bean可以通过称为checkInventoryLevel和orderProduct的方法来实现业务逻辑。通过调用这些方法,客户端可以访问应用程序提供的清单服务。

企业Bean的好处由于多种原因,企业Bean简化了大型分布式应用程序的开发。首先,因为EJB容器为企业Bean提供系统级服务,所以Bean开发人员可以集中精力解决业务问题。EJB容器而不是bean开发人员负责系统级服务,例如事务管理和安全授权。

其次,由于Bean(而不是客户端)包含应用程序的业务逻辑,因此客户端开发人员可以专注于客户端的表示。客户端开发人员不必对实现业务规则或访问数据库的例程进行编码。结果,客户端变薄了,这对于在小型设备上运行的客户端而言尤其重要。

第三,由于企业bean是可移植的组件,因此应用程序组装者可以从现有bean构建新应用程序。这些应用程序只要使用标准API,就可以在任何兼容的Java EE服务器上运行。

何时使用企业Bean如果您的应用程序具有以下任何要求,则应考虑使用企业Bean:

该应用程序必须是可伸缩的。为了容纳越来越多的用户,您可能需要在多台计算机上分发应用程序的组件。应用程序的企业bean不仅可以在不同的机器上运行,而且它们的位置对于客户端也将保持透明。

事务必须确保数据完整性。企业bean支持事务,即管理共享对象的并发访问的机制。

该应用程序将具有各种客户端。只需几行代码,远程客户端就可以轻松定位企业bean。这些客户可能很瘦,种类繁多,数量众多。


3

我最感兴趣的问题是如何以及在哪里使用它们。为了理解这一点,我们首先需要查看存在哪些类型的EJB。有2大类别:

  1. 会话豆
  2. 消息驱动的bean

让我们考虑一下会话Bean。它们有3种:

  1. 有状态的 -这些组件维护状态,并且特定于跨多个请求的客户端。将其视为会话。这些可以立即用于购物车或其他类型的会话(登录会话等)
  2. 无状态 -这些是自包含的组件,它们不会在请求之间保留信息,但是对用户而言是唯一的。想到立即使用- 服务层中的服务类。想象一下OrderService。这些的另一个大用途是公开Web服务。同样,这在服务层或完全独立。
  3. 单例 -这些是每个应用程序都存在的Bean,仅创建一次,并且可以多次重用/访问。立即Configuration想到该组件-您可以在其中存储应用程序级别的配置,并在需要时从任何地方访问它们。

现在,在任何此类情况下,其余功能或功能都可以跨层使用:

  • 安全性 -您可以在调用的方法上使用注释检查权限。如果您愿意,这可以在服务层以及控制器中发生。
  • 事务管理 -这是服务层或持久层中的明显候选者
  • 依赖注入 -再次将在各处使用

现代时代的一大用途是所谓的微服务和面向服务的体系结构。您可以将一些业务逻辑组件打包为EJB,并将它们分布在整个组织中,以供多个客户端使用(这里的客户端是指其他后端应用程序)。

等等。现在最大的缺点是您变得非常依赖EJB容器,尽管可以在两个参考实现之间进行切换,但是您将无法切换到较轻的东西-例如Tomcat。但是,为什么要牺牲所有利益呢?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.