EJB 有什么用

What use are EJBs

提问人:Raedwald 提问时间:4/7/2011 更新时间:11/5/2013 访问量:16994

问:

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

似乎有人用它们来包含业务逻辑,用于实现常规 3 层架构的业务层。这将域逻辑与域对象分离,导致域模型贫血。但这违背了我所有的 OOD 直觉;我同意马丁·福勒(Martin Fowler)的观点,这是一种反模式。我是否应该放松对贫血领域模型的反对意见?还是 EJB 有其他用途?

Java Jakarta-EE EJB

评论

2赞 Elad 4/7/2011
它是一种反模式,这就是为什么 Java EE 多年来一直在下降的原因。10年前,这似乎是个好主意。我不会放松你的正确反对意见,而是首先避免进入 EJB。
5赞 Heiko Rupp 4/7/2011
Elad:关于衰落——你从哪里得到这个想法?
8赞 Michael Borgwardt 4/7/2011
@Elad:在过去的 5 年里,您似乎没有研究过 Java EE。它已经改进了很多,并且当之无愧地重新获得了很多人气。
1赞 Lukas Eder 4/7/2011
@Elad:Java EE 不仅仅是 EJB 的容器。即使没有引入 EJB 3.x,它仍然非常强大。
0赞 Raedwald 4/8/2011
相关问题:stackoverflow.com/questions/2333307/...

答:

5赞 Heiko Rupp 4/7/2011 #1

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

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

消息驱动 Bean 充当异步通信的端点,并且可以调用会话 Bean 上的方法作为示例。

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

如果在 EJB 中写入

@Resource DataSource x;

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

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

在 EJB 3 中,EJB 1.x 和 2.x 中的旧 EntityBeans 消失了,取而代之的是 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();
    }
}

评论

0赞 Raedwald 4/7/2011
“Session Beans often server as Facade”,您认为这是作为域对象的 Facade 的主要用途吗?
0赞 Heiko Rupp 4/7/2011
不是主要用途,但很受欢迎。特别是 wrt 域对象,SB 还包含查询它们和处理 ORM 框架的逻辑。
3赞 Raedwald 4/7/2011
stackoverflow.com/questions/4773927/......强调“必须自己启动和提交/回滚事务的要求消失了”
5赞 Michael Borgwardt 4/7/2011 #2

几点:

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

评论

0赞 Dead Programmer 4/7/2011
@Michael Borgwardt:第一点的所有这些服务甚至在春季提供。
3赞 Michael Borgwardt 4/7/2011
@Suresh:那又怎样?EJB 容器在 Spring 存在之前就提供了它们。
2赞 Michael Borgwardt 4/7/2011
@Raedwald:不,我是说强行将所有逻辑排除在领域模型之外,与将更专业或更复杂的逻辑放入单独的类中以实现关注点分离是有区别的。
1赞 Heiko Rupp 4/7/2011
EJB 3 没有 EntityEJB - EntityBeans 是 EJB 1.x 和 2.x
3赞 Michael Borgwardt 4/8/2011
@Raedwald:来自同一篇文章:“如果业务规则逻辑跨越两个或多个实体对象,那么它应该成为服务类的一部分。请注意,本文还考虑了服务类是域层的一部分。
1赞 Dead Programmer 4/7/2011 #3

无状态和有状态企业 java-bean

ejb-stateless-session-beans-和-stateful-session-bean

6赞 vickirk 4/7/2011 #4

使用 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 而不是任何其他技术,只是想指出,使用它们并不意味着你的实现不能使用最佳实践。

评论

0赞 Raedwald 4/7/2011
stackoverflow.com/questions/3587289/......Concurs: “EJB 通常作为服务类在服务层中”
3赞 Manuel Salvadores 4/7/2011 #5

只是个人经验的一句话......

我不怀疑 EJB 的好处,但与我合作过后,我认为 EJB 只适合在安全性和交易非常重要的情况下(即:金融应用程序)。对于 90% 的情况,没有 EJB 就没问题了。另一件事......可伸缩性和 EJB 不是好朋友。

评论

1赞 Heiko Rupp 4/7/2011
你从哪里得到最后一个想法?EJB 非常适合扩展。
0赞 Manuel Salvadores 4/7/2011
好吧,如果这是真的,我们将看到更多使用率很高的门户网站使用它们(Twitter、Facebook、Google 等)。正如我所说,如果您的系统大量使用事务和安全性,那么 EJB 可能是一个不错的选择,否则在大多数情况下,它们会矫枉过正。
0赞 vickirk 4/7/2011
@msalvadores不了解Twitter,但Facebook和Google有自己的框架,高度配置了他们需要的东西。大多数企业负担不起为此专门负责的庞大团队。JEE 运营着数量惊人的全球业务,这是有原因的,易于部署、低开发成本和良好的可扩展性是其中一些原因。在企业层面,没有什么(恕我直言)可以与之相提并论。
2赞 vickirk 4/7/2011
我没有进行长时间的讨论(可能是最后一条评论),但如果您不需要交易/安全性,那么它就不会使用交易/安全性,也不会使用额外的资源。但是,可以肯定的是,如果您只想托管一项琐碎的服务,那就太复杂了。您的观点是可伸缩性,EJB 是可扩展的,与我使用过的所有 EJB 容器有关是微不足道的。
1赞 Arjan Tijms 4/12/2011
但是有了 EJB,管理事务的痛苦就大大减少了,以至于变得微不足道。这大大提高了简单和复杂应用的鲁棒性。从本质上讲,幕后事务仍然很复杂,但 EJB 使它们变得容易。正如 FK 的实现在内部可能很复杂一样,但您的数据库使向列添加 FK 变得微不足道。
23赞 Arjan Tijms 4/12/2011 #6

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

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

它们通过提供声明性事务(如果一个事务尚未进行,每个输入方法都会自动启动事务,尽管如果需要可以更改),池化,安全性,锁定,远程处理等等,它们在这里有很大帮助。有关其他详细信息,请参阅以下答案:

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

EJB 使管理事务变得微不足道。如果没有 EJB,就有很多用于启动、提交或回滚 tx 的样板代码。

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

然而,由于池化,只注入非常轻量级的存根,这更类似于一种指向实际实例的 URL。这些在内存或 CPU 开销方面几乎没有成本。

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

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

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

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

评论

0赞 Tom Anderson 5/21/2012
您提到池化允许使用轻量级存根。CDI 也使用存根,但不使用池化。我宁愿怀疑池化是 EJB1/2 的遗留问题,它可能是一个好主意,但现在几乎毫无意义,甚至可能有害。
0赞 Arjan Tijms 5/22/2012
池化可能仍然有其用途,但是在那些不必要或有害的情况下,让它选择加入或选择退出肯定是有话要说的。目前,使用 @Stateless您可以在一个注释中获得所有内容。无论如何,即使在 EJB3 中,实例化依赖关系(可能是外部系统)也可能很昂贵,然后池化绝对是有用的。
0赞 Tom Anderson 5/22/2012
是的,这一切都归结为昂贵的依赖关系。但是,我认为这就是 JCA 资源助手的用途 - 管理昂贵的资源,尤其是外部连接。使用资源适配器可以仅池化资源,而不必池化资源注入到的对象。可悲的是,编写池化 EJB 比编写资源适配器要容易得多。
1赞 Arjan Tijms 7/19/2014
@Geek 代理不一定必须包含任何数据或太多逻辑。它可能是一个小包装器,对于每个调用的方法方法 X 只说:“从池 A 中获取 bean ”xyz.foo.kaz“ 并调用方法 X”。实际上,您可以将其视为只是对“A://xyz.foo.kaz/X”执行类似 http 请求的事情。代理可能非常轻量级,因为它甚至不需要包含对真实 Bean 的引用,只需要池的“命令/请求”。
1赞 Geek 7/19/2014
@ArjanTijms我现在明白你的意思了。感谢您的跟进和 +1。
2赞 Majed 4/15/2011 #7

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

例如,POJO 无法处理事务,因此在 EJB 中,您可以指定特定方法的事务类型,该方法是否需要新事务,或者它不是来自事务。

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

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