EJB 有啥用

Posted

技术标签:

【中文标题】EJB 有啥用【英文标题】:What use are EJBsEJB 有什么用 【发布时间】:2011-07-31 14:17:27 【问题描述】:

我目前正在学习 Jave-EE,拥有丰富的 C++ 经验并学习过 Java SE。我不明白 Enterprise Java Beans 的用途;有人可以为我澄清这一点。我对 legacy 用途不感兴趣:这是在 EJB-3.1 和 Java-EE 6 的上下文中。

似乎有些人用它们来包含业务逻辑,用于实现传统三层架构的业务层。这将域逻辑与域对象分开,导致anemic domain model。但这违背了我所有的 OOD 直觉;我同意 Martin Fowler 的观点 it is an anti-pattern。我应该放松对贫血域模型的反对意见吗?或者 EJB 还有其他用途吗?

【问题讨论】:

这是一种反模式,这就是为什么 Java EE 多年来一直在下降。这在 10 年前可能看起来是个好主意。我不会放松您的正确反对意见,而是首先避免涉及 EJB。 Elad:在下降 - 你从哪里得到这个想法? @Elad:您似乎在过去 5 年没有研究过 Java EE。它已经改进了很多,当之无愧地重新获得了很多人气。 @Elad:Java EE 不仅仅是 EJB 的容器。即使没有引入 EJB 3.x,它仍然非常强大。 相关问题:***.com/questions/2333307/… 【参考方案1】:

正如其他几个答案所示,EJB 非常适合实现服务层。它们是 Java EE 中一种非常现代、轻量级的 bean。尽管有这个名字,但您无法将它们与 J2EE 中严苛的重量级 EJB2 野兽相提并论。每个人都同意那些是一场灾难,但现在已经不是 2002 年了。

自 EJB3 (2006) 以来,EJB bean 一直是一项完美的技术。

它们通过提供声明性事务(如果一个尚未在进行中的事务,尽管可以根据需要更改)、池化、安全性、锁定、远程处理,然后一些。有关其他详细信息,请参阅以下答案:

Frameworks for Layering reusable Architectures In what situations are EJBs used ? Are they required in websites/ web-application development? EJB 3 or Hibernate 3 @EJB injection vs lookup - performance issue

这里已经解释了事务,但要补充一点:它不仅仅是高度复杂、高度安全的系统需要的东西。我会说这是一个基本要求,即使只处理数据库也是如此。如果我处理一个简单的订单,我希望库存和订单都更新或根本不更新。这与在数据库中包含 PK 和 FK 以确保完整性一样基本。

EJB 使管理事务变得轻而易举。如果没有 EJB,就会有很多用于启动、提交或回滚 tx 的样板代码。

也不应低估 EJB 提供的池化和存根的好处。这意味着一个 bean 可以注入大量 EJB,您不必担心每次创建此类 bean 时都会实例化它们。否则,当并非每次都使用所有 EJB 时,这将特别麻烦。

但是,由于池化,只注入了非常轻量级的存根,这更类似于一种指向实际实例的 URL。就注入的内存或 CPU 开销而言,这些成本几乎为零。

EJB 还具有注释来声明它们是单例,安排它们的锁定行为(写锁/读锁),声明一个应该在启动时启动,允许它们管理所谓的扩展持久性上下文(一个没有作用域的持久性上下文到 TX)等。

这些都是您不希望在您的 slim 实体中出现的所有问题。在许多架构中,例如 User 对象是我想要跨层发送的简单数据实体。我不希望我的 User 实例有一个 sendMsg() 方法并且有一个 JMS 资源作为依赖项,因此可以突然从某个客户端完成消息发送。我不太确定为什么人们认为这在某种程度上是“自然的”和“OOP”。

在现实世界中,每当我想向他发送明信片时,我也不会对我的朋友 Joe 调用 sendMsg 操作。取而代之的是,我给一张卡片写地址,然后把它带到邮局或放在邮箱里。

我也不会在蛋糕上调用 bake() 操作。相反,我将蛋糕放入烤箱等。

【讨论】:

您提到池化允许使用轻量级存根。 CDI 也使用存根,但不使用池。我宁愿怀疑池化是 EJB1/2 的遗留物,它可能是一个好主意,但现在几乎没有意义,甚至可能有害。 Pooling 可能仍然有它的用途,但是对于那些不必要或有害的情况,让它选择加入或退出肯定是有道理的。目前使用@Stateless,您可以在一个注释中获得所有内容。无论如何,即使在 EJB3 中实例化一个依赖项(可能是一个外部系统)也可能很昂贵,然后池化肯定是有用的。 是的,这一切都归结为昂贵的依赖关系。但是,我认为这就是 JCA 资源适配器的用途——管理昂贵的资源,尤其是外部连接。使用资源适配器可以让您只汇集资源,而不必汇集资源注入的对象。遗憾的是,编写池化 EJB 比编写资源适配器容易得多。 @Geek 代理不一定要包含任何数据或太多逻辑。它可能是一个小包装器,对于每个调用的方法方法 X 只说:“从池 A 中获取 bean“xyz.foo.kaz”并调用方法 X”。实际上,您可以 将其视为对“A://xyz.foo.kaz/X”的 http 请求之类的操作。代理可以是非常轻量级的,因为它甚至不需要包含对真实 bean 的引用,只需要包含池的“命令/请求”。 @ArjanTijms 我现在明白你的意思了。感谢您的跟进和 +1。【参考方案2】:

使用 Java EE 并不会自动暗示一个贫乏的领域模型,就像你可以用 java 编写代码一样,没有很好地利用最佳实践并不意味着它在 java 中是不可能的。我相信 Martin Fowler 的观点是 J2EE(注意使用 J2EE 而不是 Java EE)几乎强制执行逻辑和数据操作。使用基于 POJO 的实体允许对数据和行为进行适当建模。 EJB 中的“业务逻辑”通常会编排业务逻辑的应用程序,但通常不会实际执行它,它通常是一个非常薄的包装器。

EJB 就这样构成了您的服务 API,无论您使用哪个平台/框架,您都需要它,您需要有一些可以物理调用的东西,它是一个入口点。无论您是使用 Spring、Web 服务等实现...您需要一个服务层,没有什么可以阻止它在 Java EE 中实现。一个相当人为的例子

@Stateless
public SomeServiceImpl implements SomeService
    someServiceMethod() 
       delegate.doSomething();
    


public SomeServiceDelegate implements SomeService
    someServiceMethod() 
       modelObject.doSomething();
    

我不会详细说明选择 EJB 而不是任何其他技术的原因,只是想指出使用它们并不意味着您的实现不能使用最佳实践。

【讨论】:

***.com/questions/3587289/… 同意:“ejb 通常在服务层作为服务类”【参考方案3】:

您已经引用了“实现业务逻辑”用例。

EJB - 在 EJB 3.x 会话 Bean、消息驱动 Bean 和 3.1 中新的单例 Bean 确实允许您实现业务逻辑。 会话 Bean 通常作为客户端连接的 Facade 服务。这些客户端可以是 Servlet,通过例如服务提供内容。 HTTP 或通过其他(更多二进制)协议与 EJB 通信的“胖”客户端。

Message Driven Beans 充当异步通信的端点,并且可以自己调用会话 Beans 上的方法作为示例。

所有 EJB 都有一个共同点,这使得它们非常有吸引力:它们由容器管理。所以容器负责实例化、池化、事务、安全等。

如果你用 EJB 编写

@Resource DataSource x;

容器确保当您的 bean 准备好接收方法调用时,变量“x”包含合适的数据源。

Bean 池允许您有更多的客户端连接到一个站点,而不是没有,因为实例是共享的(无状态 SB),或者如果内存紧张,实例可以由容器换出到第二个存储并在以后重新激活它们。

在 EJB 3 中,EJB 1.x 和 2.x 中的旧 EntityBeans 已不复存在并被 JPA 取代,JPA 构建了 POJO 的域数据模型,它可以被注释以提供关系语义,也可以是语义由外部 XML 文件提供。

使用 JPA(根本不需要 EJB),EJB 通常用于实现对这些实体的处理:

@Stateless
public class MyBean 
    @PersistenceContext EntityManager em;

    public Foo getFoo(String name) 
        Query q = em.createQuery("SELECT f FROM Foo f WHERE f.name = :name");
        q.setParameter("name",name);
        return q.getSingleValue();
    

【讨论】:

“Session Beans 通常作为 Facade 服务”你认为这是主要用途吗,作为域对象的 Facade?​​span> 不是主要用途,但很流行。特别是对于域对象,SB 还包含查询它们和处理 ORM 框架的逻辑。 ***.com/questions/4773927/… 强调“必须自己启动和提交/回滚事务的要求消失了”【参考方案4】:

几点:

EJB 本身并不存在;它们存在于 EJB 容器中,通过它们为您提供一些非常有用的服务,例如声明式安全、声明式事务和相对简单的集群。 虽然贫血的领域模型确实是一种反模式:一旦您的业务逻辑变得更加复杂,例如当多个应用程序在同一个模型上运行时,将大部分逻辑与模型分离就变成了关注点分离的问题。

【讨论】:

@Michael Borgwardt:第一点的所有这些服务甚至由 spring 提供。 @Suresh:那又怎样? EJB 容器在 Spring 存在之前就提供了它们。 @Raedwald:不,我是说强制将 all 逻辑排除在领域模型之外,与将更专业或复杂的逻辑放入单独的类中来实现之间是有区别的关注点分离。 EJB 3 没有 EntityEJB - EntityBean 是 EJB 1.x 和 2.x @Raedwald:来自同一篇文章:“如果业务规则逻辑跨越两个或更多实体对象,那么它应该成为服务类的一部分。” - 无状态会话 EJB 就是这样,一个服务类。请注意,本文还将服务类视为领域层的一部分。【参考方案5】:

只是个人经验的评论......

我不怀疑 EJB 的好处,但在使用过 EJB 之后,我发现 EJB 只适用于安全性和事务非常重要的情况(例如:金融应用程序)。对于 90% 的情况,没有 EJB 就可以了。另一件事...可伸缩性和 EJB 不是好朋友。

【讨论】:

你最后的想法是从哪里来的? EJB 非常适合扩展。 好吧,如果这是真的,我们会看到使用它们的门户网站使用率更高(推特、脸书、谷歌……)。正如我所说,如果您的系统大量使用事务和安全性,那么也许 EJB 是一个不错的选择,否则就像在大多数情况下它们是矫枉过正的。 @msalvadores 不了解 twitter,但 facebook 和 google 有自己的框架,高度配置为他们需要的。大多数企业负担不起为此专门设立庞大的团队。 JEE 运行着数量惊人的全球业务,这是有原因的,易于部署、低开发成本和良好的可扩展性是其中一些原因。在企业层面,没有什么(恕我直言)可以接近。 我不会进行长时间的讨论(可能是最后一条评论),但如果您不需要事务/安全性,那么它就不会使用,也不会使用额外的资源。但可以肯定的是,如果您想做的只是托管一项微不足道的服务,那就太复杂了。你的观点是可扩展性,EJB 是可扩展的,而且我使用的所有 ejb 容器都很容易做到。 但是使用 EJB,管理事务的痛苦大大减少,变得微不足道。这极大地提高了简单和复杂应用程序的稳健性。底层事务本质上仍然很复杂,但 EJB 使它们变得简单。正如 FK 的实现在内部可能很复杂,但您的数据库使向列添加一个变得微不足道。【参考方案6】:

有些人在这样的讨论中说 EJB 在 EJB3 中变得有用不是在那之前,这不是真的。 是的,它特别是使用 JPA 变得更加强大,但是 EJB1.0 和 EJB2.1 仍然做了很多。 也许他们没有在大型应用程序中使用它,所以他们这么说。

例如 POJO 不能处理事务,因此在 EJB 中,您可以为特定方法指定事务类型是需要新事务还是不来自事务。

在我的组织中,我们使用从头开始构建 ERP,我们在业务逻辑中使用 EJB,它是从 2000 年开始的,EJB 是 1.0 版。 它不仅将业务层与其他层分开,而且还将系统彼此分开, 例如: 财务模块与人力资源模块分开。 如果他们想添加一个新模块,他们可以在不重新启动系统的情况下添加它,它将以完美的方式与系统集成..

并在 EJB 中记住这一点: 您在代码中看到的什么都不是,而 EJB 容器正在为您做的就是一切 :)。

【讨论】:

【参考方案7】:

stateless-and-stateful-enterprise-java-beans

ejb-stateless-session-beans-and-stateful-session-bean

【讨论】:

以上是关于EJB 有啥用的主要内容,如果未能解决你的问题,请参考以下文章

在 Web 应用程序中使用 EJB 有啥好处?

java里的自定义注解类型 有啥用?

spring框架的核心概念:IoC和AOP到底有啥用?

EJB 教程推荐

EJB 依赖于另一个 EJB?

EJB开发基础——EJB规范