我目前正在学习Jave-EE,拥有丰富的C ++经验并学习过Java SE。我不明白Enterprise Java Beans的目的;有人可以为我澄清这一点。我对遗留的使用不感兴趣:这是在EJB-3.1和Java-EE 6的上下文中。
似乎有些人使用它们来包含业务逻辑,用于实现传统3层架构的业务层。这将域逻辑与域对象分开,从而导致anemic domain model。但这违背了我所有的OOD本能;我同意Martin Fowler it is an anti-pattern。我是否应该放松对贫血领域模型的反对意见?或者EJB有其他用途吗?
答案 0 :(得分:19)
如其他几个答案所示,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)等。
这些都是您在 slim 实体中不需要的所有问题。在许多体系结构中,例如,User对象是我想跨层发送的简单数据实体。我不希望我的User实例具有sendMsg()方法并且具有JMS资源作为依赖项,因此可以突然从某个客户端完成消息发送。我不确定为什么人们会认为这是'自然'和'OOP'。
在现实世界中,每当我想给他寄明信片时,我也不会对我的朋友Joe调用sendMsg操作。相反,我会发一张卡片并将其带到邮局或将其放入邮箱。
我也没有在蛋糕上调用bake()操作。相反,我把蛋糕放在烤箱等等。
答案 1 :(得分:6)
您已经引用了“实现业务逻辑”用例。
EJB - 在EJB 3.x会话Bean,消息驱动Bean和3.1中,新的Singleton Beans确实允许您实现biz逻辑。 会话Bean通常作为客户端连接的Facade服务器。这些客户端可以是Servlet,通过例如服务内容HTTP或“胖”客户端,通过其他(更多二进制)协议与EJB进行通信。
Message Driven Beans作为异步通信的端点,可以自己调用Session Beans上的方法作为示例。
所有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();
}
}
答案 2 :(得分:6)
使用Java EE并不会自动暗示一个贫血的域模型,就像你在java中编写代码一样,没有充分利用最佳实践并不意味着它在java中是不可能的。我相信Martin Fowler的观点是J2EE(注意使用J2EE而不是Java EE)几乎强制执行逻辑和数据操作。使用基于POJO的实体允许数据和行为适当地建模。 EJB中的“业务逻辑”通常编排业务逻辑的应用程序,但通常不会实际执行它,它通常是一个非常薄的包装器。
因此,EJB构成了您的Service API,您需要使用您正在使用的任何平台/框架,您需要拥有可以物理调用的东西,这是一个切入点。无论您是使用spring,Web服务等实现......您需要一个服务层,没有什么能阻止它在Java EE中实现。一个相当人为的例子@Stateless
public SomeServiceImpl implements SomeService
someServiceMethod() {
delegate.doSomething();
}
}
public SomeServiceDelegate implements SomeService
someServiceMethod() {
modelObject.doSomething();
}
}
我没有考虑更喜欢EJB而不是任何其他技术的原因,只是想指出使用它们并不意味着你的实现不能使用最佳实践。
答案 3 :(得分:5)
有几点:
答案 4 :(得分:3)
只是个人经历的评论......
我不怀疑EJB的好处,但是曾经使用它们,我认为EJB只适用于安全性和事务非常重要的情况(即:财务应用程序)。对于90%的情况,没有EJB就可以了。另一件事......可伸缩性和EJB不是好朋友。
答案 5 :(得分:2)
有些人在这样的讨论中告诉我,在此之前,EJB在EJB3中变得有用,而这并不是真的。 它特别适用于JPA变得更强大,但EJB1.0和EJB2.1仍然做了很多。 也许他们没有在大型应用程序中使用它,所以他们说。
例如,POJO无法处理事务,因此在EJB中,您可以为特定方法指定事务类型,因为它需要新事务,或者它不是来自事务。在我的组织中,我们从头开始使用ERP构建,我们在业务逻辑中使用EJB,它来自2000,EJB是版本1.0。 它不仅将业务层与其他层分开,而且还将系统彼此分开, 例如: 财务模块与人力资源模块分开。 如果他们想要添加一个新模块,他们可以在不重新启动系统的情况下添加它,它将以完美的方式与系统集成。
并在EJB中记住这一点: 你在代码中看到的东西是什么,EJB容器为你做的是每件事:)。
答案 6 :(得分:1)