何时使用Spring或EJB3或同时使用它们,是必要的还是方便的?

47

我有些困惑于混合使用JSF2+Spring+EJB3或其任何组合。我知道Spring的主要特点之一是依赖注入,但使用JSF托管的bean时,我可以使用@ManagedBean@ManagedProperty注释来实现依赖注入功能。对于EJB3,我更加困惑何时将其与JSF一起使用,或者是否有理由使用它。

那么,在什么情况下使用Spring+JSF2或EJB3+JSF2会是一个好主意呢?

到目前为止,我只创建了一些小型Web应用程序,仅使用JSF2,并且从未需要使用Spring或EJB3。然而,我发现很多地方的人们都在一起使用所有这些东西。


2
主要是在需要透明的数据库事务管理和/或厌倦了所有JDBC样板代码时使用。请注意,Spring和EJB是竞争对手,通常不会混合使用。选择其中一个即可。相关链接:https://dev59.com/72cs5IYBdhLWcg3wPxnN - BalusC
谢谢您的回答,我的项目中使用了Open JPA进行数据库事务管理,使用JPA和EJB有什么区别? - user2018726
1
EJB是JavaEE的一部分,它是一种由某些应用服务器(如JBoss或GlassFish)提供的容器。这个服务器本身包含了一个JPA实现,作为JavaEE容器的一部分。此外,您还可以在Spring中配置您的JPA配置,在这种情况下,提供自己的实现(可以是EclipseLink、Hibernate等)。 - Aritz
4
与JDBC类似,JPA完全没有自动事务管理。您仍需要自行管理(t = em.getTransaction(), t.begin(), t.commit()等)。JPA不是事务管理API,而是ORM API。 - BalusC
2个回答

79

首先,Spring和EJB(+JTA)是竞争性技术,通常不会在同一个应用程序中同时使用。选择其中一个。Spring或者EJB(+JTA)。我不会告诉你该选择哪一个,我只会给你一些历史和事实,以便于你更容易做出决定。


它们试图解决的主要问题是提供具有自动事务管理的业务服务层API。想象一下,您需要发出多个SQL查询才能执行单个业务任务(例如下订单),其中一个查询失败了,那么您当然希望所有都可以回滚,以便将数据库保持为与之前完全相同的状态,就像完全没有发生任何事情一样。如果您没有使用事务,则数据库将处于无效状态,因为第一组查询实际上已成功执行。

如果您熟悉基本的JDBC,则应该知道可以通过在连接上关闭自动提交,然后按顺序发送这些查询,然后在catch (SQLException)中执行rollback()之前在同一个try块中执行commit()来实现这一点。然而,这很烦琐,需要每次都手动实现。

使用Spring和EJB(+JTA),默认情况下,单个(无状态的)业务服务方法调用会透明地计算为一个完整事务。这样,您就不需要担心事务管理了。您不需要手动创建EntityManagerFactory,也不需要像将业务服务逻辑紧密耦合到JSF后备bean类中或在JPA中使用RESOURCE_LOCAL而不是JTA时那样明确调用em.getTransaction().begin()等。例如,您可以只有以下使用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;,并在动作方法中调用orderService.placeOrder(newOrder);,那么将执行单个完整事务。例如,如果updateQuantity()调用或persist()调用之一失败并引发异常,则会回滚到目前为止执行的任何updateQuantity()调用,并使DB处于干净和清晰状态。当然,你可以在JSF后备bean中捕获该异常并显示faces消息之类的内容。

需要注意的是,“Spring”是一个相当大的框架,它不仅与EJB竞争,还与CDI和JPA竞争。以前,在黑暗的J2EE时代,当EJB 2.x难以实现时(上述EJB 3.x OrderService示例需要至少5倍的代码以及一些XML代码),Spring提供了一个更好的选择,其要求更少的Java代码(但仍需要很多XML代码)。J2EE/EJB2从Spring中吸取了教训并推出了Java EE 5,该版本提供了新的EJB3 API,比Spring更加流畅,而且根本不需要XML。

Spring还提供IoC/DI(控制反转;依赖注入)。在J2EE时代,这是通过XML配置的,但现在已经不再需要。自从Java EE 6之后,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样板代码(但并不完全代表业务服务层)。

另请参阅:


5

这里没有真正容易的答案,因为Spring有多种用途。

在较高的层面上,Spring与Java EE竞争,这意味着您可以将它们中的任何一个用作全栈框架。

在更细粒度的级别上,Spring IoC容器和Spring Beans与Java EE中CDI&EJB的组合相竞争。

至于Web层,Spring MVC与JSF竞争。一些Spring xyzTemplate与JPA接口竞争(两者都可以使用Hibernate作为实现)。

您可以混合搭配使用;例如,将CDI和EJB bean与Spring MVC一起使用,或将Spring Beans与JSF一起使用。

通常不会直接使用两种竞争技术。在同一个应用程序中使用Spring Beans + CDI + EJB,或Spring MVC + JSF是愚蠢的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接