首先,Spring 和 EJB(+JTA) 是相互竞争的技术,通常不能在同一个应用程序中一起使用。选择一个或另一个。弹簧或EJB(+JTA)。我不会告诉你选择哪个,我只会告诉你一点历史和事实,以便你更容易做出决定。
他们试图解决的主要问题是提供具有自动事务管理的业务服务层 API。想象一下,您需要触发多个 SQL 查询来执行单个业务任务(例如下订单),其中一个失败了,那么您当然希望一切都回滚,以便数据库保持相同的状态和以前一样,好像什么都没发生过一样。如果您不使用事务,那么数据库将处于无效状态,因为第一批查询实际上成功了。
如果您熟悉基本的 JDBC,那么您应该知道这可以通过关闭连接上的自动提交来实现,然后按顺序触发这些查询,然后在执行acommit()
时执行相同try
的操作。然而,每次实施都非常乏味。catch (SQLException)
rollback()
使用 Spring 和 EJB(+JTA),单个(无状态)业务服务方法调用默认透明地计为单个完整事务。这样,您根本不需要担心事务管理。当您将业务服务逻辑紧密耦合到 JSF 支持 bean 类和/或在 JPA中使用而不是使用时,您不需要手动创建EntityManagerFactory
,也不需要显式调用和。例如,您可能只有以下使用 JPA 的 EJB 类:em.getTransaction().begin()
RESOURCE_LOCAL
JTA
@Stateless
public class OrderService {
@PersistenceContext
private EntityManager em;
@EJB
private ProductService productService;
public void placeOrder(Order newOrder) {
for (Product orderedproduct : newOrder.getProducts()) {
productService.updateQuantity(orderedproduct);
}
em.persist(newOrder);
}
}
如果您@EJB private OrderService orderService;
的 JSF 支持 bean 中有一个并调用orderService.placeOrder(newOrder);
action 方法中的 ,那么将执行一个完整的事务。例如,如果其中一个updateQuantity()
调用或persist()
调用因异常而失败,那么它将回滚迄今为止执行的所有updateQuantity()
调用,并使数据库保持干净和清晰的状态。当然,您可以在 JSF 支持 bean 中捕获该异常并显示一条面孔消息左右。
需要注意的是,“Spring”是一个相当大的框架,它不仅与 EJB 竞争,还与 CDI 和 JPA 竞争。以前,在黑暗的 J2EE 时代,当 EJB 2.x 难以实现时(上面的 EJB 3.xOrderService
示例在 EJB 2.x 中需要至少 5 倍以上的代码和一些 XML 代码)。Spring 提供了一个更好的替代方案,它需要更少的 Java 代码(但仍然需要很多 XML 代码)。J2EE/EJB2 从 Spring 中吸取了教训,并附带了 Java EE 5,它提供了新的 EJB3 API,它比 Spring 更流畅,根本不需要 XML。
Spring 还提供了开箱即用的 IoC/DI(控制反转;依赖注入)。这是在由 XML 配置的 J2EE 时代,这可能有点过火了。现在 Spring 也使用注解,但仍然需要一些 XML。从 Java EE 6 开始,在吸取了 Spring 的教训之后,CDI 开箱即用,提供相同的 DI 功能,但不再需要 XML。使用 Spring DI @Component
/@Autowired
和 CDI @Named
/@Inject
您可以实现与 JSF 使用@ManagedBean
/相同的效果@ManagedProperty
,但是 Spring DI 和 CDI 围绕它提供了更多优势:例如,您可以编写拦截器来预处理或后处理托管 bean 创建/销毁或托管 bean 方法调用,您可以创建自定义范围、生产者和消费者,您可以在范围更广的实例中注入更窄范围的实例等。
Spring 还提供 MVC,它本质上是与 JSF 竞争的。将 JSF 与 Spring MVC 混合使用是没有意义的。此外,Spring 还提供了 Data,它本质上是 JPA 之上的一个额外抽象层,进一步最小化了 DAO 样板(但它本质上并不代表整个业务服务层)。
也可以看看: