什么时候需要或方便地使用 Spring 或 EJB3 或同时使用它们?
Posted
技术标签:
【中文标题】什么时候需要或方便地使用 Spring 或 EJB3 或同时使用它们?【英文标题】:When is it necessary or convenient to use Spring or EJB3 or all of them together? 【发布时间】:2013-08-24 12:42:03 【问题描述】:我对 JSF2+Spring+EJB3 或它们的任意组合的混合使用有点困惑。我知道 Spring 的主要特征之一是依赖注入,但是对于 JSF 托管 bean,我可以使用 @ManagedBean
和 @ManagedProperty
注释,并获得依赖注入功能。对于 EJB3,我更加困惑于何时将它与 JSF 一起使用,或者是否有理由使用它。
那么,在什么情况下使用 Spring+JSF2 或 EJB3+JSF2 比较好呢?
到目前为止,我只使用 JSF2 创建了一些小型 Web 应用程序,并且从未需要使用 Spring 或 EJB3。但是,我在很多地方看到人们一起处理所有这些东西。
【问题讨论】:
主要是当您需要透明的数据库事务管理和/或当您厌倦了所有 JDBC 样板代码时。请注意,Spring 和 EJB 是相互竞争的,通常不会混合在一起。选择一个或另一个。相关:***.com/questions/13011392/jsf-service-layer 感谢您的回答,在我的项目中,我使用 open JPA 进行 DB 事务管理,使用 jpa 或 EJB 有什么区别? EJB 是 JavaEE 的一部分,JavaEE 是一些应用服务器(如 JBoss 或 GlassFish)提供的容器。该服务器本身包含一个 JPA 实现,作为 JavaEE 容器。你也可以在 Spring 中配置你的 JPA 配置,在这种情况下你自己提供一个实现(可以是 EclipseLink、Hibernate..) 和 JDBC 一样,JPA 根本没有自动事务管理。您仍然需要自己管理它(t = em.getTransaction()
、t.begin()
、t.commit()
等)。 JPA 不是事务管理 API,而是 ORM API。
【参考方案1】:
首先,Spring 和 EJB(+JTA) 是相互竞争的技术,通常不能在同一个应用程序中一起使用。选择一个或另一个。 Spring 或 EJB(+JTA)。我不会告诉你选择哪个,我只会告诉你一点历史和事实,以便你更容易做出决定。
他们试图解决的主要问题是提供具有自动事务管理功能的业务服务层 API。想象一下,您需要触发多个 SQL 查询来执行单个业务任务(例如下订单),其中一个失败了,那么您当然希望 everything 回滚,这样DB 保持与以前相同的状态,就好像完全没有发生任何事情一样。如果您不使用事务,那么数据库将处于无效状态,因为第一批查询实际上成功了。
如果您熟悉基本的 JDBC,那么您应该知道这可以通过关闭连接上的自动提交来实现,然后依次触发这些查询,然后在相同的 try
中执行 commit()
执行catch (SQLException)
rollback()
。然而,每次都执行这个tedious。
使用 Spring 和 EJB(+JTA),单个(无状态)业务服务方法调用默认透明地计为单个完整事务。这样,您根本不需要担心事务管理。您不需要手动创建EntityManagerFactory
,也不需要显式调用em.getTransaction().begin()
,例如当您将业务服务逻辑紧密耦合到JSF 支持bean 类和/或使用RESOURCE_LOCAL
而不是@ JPA 中的 987654332@。例如,您可能只有以下使用 JPA 的 EJB 类:
@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);
如果您的 JSF 支持 bean 中有一个 @EJB private OrderService orderService;
并在 action 方法中调用 orderService.placeOrder(newOrder);
,那么将执行一个完整的事务。例如,如果updateQuantity()
调用或persist()
调用之一因异常而失败,那么它将回滚迄今为止执行的所有updateQuantity()
调用,并使数据库保持干净和清晰的状态。当然,您可以在 JSF 支持 bean 中捕获该异常并显示一条面孔消息左右。
需要注意的是,“Spring”是一个相当大的框架,不仅与EJB竞争,还与CDI和JPA竞争。以前,在黑暗的 J2EE 时代,当 EJB 2.x 难以实现时(上面的 EJB 3.x OrderService
示例在 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 样板(但它本质上并不代表整个业务服务层)。
另见:
What exactly is Java EE? JSF Controller, Service and DAO @Stateless beans versus @Stateful beans【讨论】:
【参考方案2】:这里没有真正简单的答案,因为 Spring 有很多东西。
在非常高的水平上,Spring 与 Java EE 竞争,这意味着您可以将其中任何一个用作完整的堆栈框架。
在更细粒度的级别上,Spring IoC 容器和 Spring Bean 与 Java EE 中的 CDI 和 EJB 组合竞争。
在 Web 层方面,Spring MVC 与 JSF 竞争。一些 Spring xyzTemplate 与 JPA 接口竞争(两者都可以使用 Hibernate 作为这些接口的实现)。
可以混搭;例如,将 CDI 和 EJB bean 与 Spring MVC 一起使用,或者将 Spring Beans 与 JSF 一起使用。
您通常不会同时使用 2 个直接竞争的技术。 Spring bean + CDI + EJB 在同一个应用中,或者 Spring MVC + JSF 很傻。
【讨论】:
以上是关于什么时候需要或方便地使用 Spring 或 EJB3 或同时使用它们?的主要内容,如果未能解决你的问题,请参考以下文章
不允许在共享 EntityManager 上创建事务 - 使用 Spring 事务或 EJB CMT