当前位置: 首页 > 知识库问答 >
问题:

在哪里使用EJB3.1和CDI?

慕容明煦
2023-03-14

我正在制作一个基于Java EE的产品,其中我使用了GlassFish 3和EJB 3.1。

我的应用程序有会话bean,一个调度程序,并且使用web服务。我最近了解了Apache TomEE,它支持上下文和依赖注入(CDI)。GlassFish容器也支持CDI。

如果我不需要CDI也不提供的任何特性,我可以替换会话bean吗?如果那样的话,我能得到什么好处呢?

共有1个答案

翟光赫
2023-03-14

是的,您可以自由地混合CDI和EJB并获得一些伟大的结果。听起来您使用的是@webservice@schedule,这是将EJB添加到组合中的好理由。

这里有很多混乱,所以这里有一些关于EJB和CDI的一般信息,因为它们是相互关联的。

请注意,EJB是CDI bean,因此具有CDI的所有优点。反之亦然。因此,绝对不要养成“EJB vs CDI”的习惯,因为这种逻辑实际上会转化为“EJB+CDI vs CDI”,这是一个奇怪的等式。

在Java EE的未来版本中,我们将继续对它们进行调整。对齐意味着允许人们做他们已经能做的事情,只是在顶部没有@statefule@stateless@singleton注释。

最终,EJB和CDI共享作为代理组件的相同基本设计。当您获得对EJB或CDI bean的引用时,它不是真正的bean。相反,给你的对象是一个假的(代理)。当您在这个假对象上调用一个方法时,调用将转到容器,容器将通过拦截器、修饰器等发送调用,并负责任何事务或安全检查。完成所有操作后,调用最终转到实际对象,结果通过代理传递回调用方。

区别只是在于如何解析要调用的对象。所谓“解析”,我们只是指容器在哪里以及如何寻找要调用的真实实例。

在CDI中,容器在一个“作用域”中查找,该作用域基本上是一个在特定时间段内存在的hashmap(每个请求@requestscoped、每个HTTP会话@sessionscoped、每个应用程序@applicationscoped、JSF会话@conversationscoped或每个自定义作用域实现)。

在EJB中,如果bean的类型为@statefule,容器还会查看hashmap。@statefulebean还可以使用上述任何一个作用域注释,从而使它与作用域中的所有其他bean一起生存和消亡。在EJB中,@statefule本质上是“任意作用域”bean。@stateless基本上是一个实例池--您可以在一次调用期间从池中获得一个实例。@singleton本质上是@applicationscoped

因此,在基本级别上,可以用“EJB”bean做的任何事情都应该可以用“CDI”bean做。在被窝里很难把他们分开。除了解析实例的方式之外,所有的管道都是相同的。

在进行代理时容器提供的服务方面,它们目前并不相同,但正如我所说的,我们正在Java EE规范级别上研究它。

忽略你可能有的任何“轻”或“重”的心理意象。那都是市场营销。他们有相同的内部设计的大部分。CDI实例解析可能更复杂一些,因为它更动态和上下文。相比之下,EJB实例解析是相当静态的、哑的和简单的。

我可以从TomEE中的实现角度告诉您,调用EJB与调用CDI bean之间的性能差别几乎为零。

当然,在没有好处的情况下不要使用CDI或EJB。当您开始需要注入、事件、拦截器、修饰器、生命周期跟踪等等时,请加入CDI。大多数时候都是这样。

除了这些基本知识之外,还有一些有用的容器服务,只有在您通过在CDI bean上添加@statefule@stateless@singleton使其成为EJB时,您才可以选择使用。

这里有一个简短的列表,说明我何时开始使用EJB。

公开JAX-WS@webservice。我很懒。当@webservice也是EJB时,您不必在web.xml文件中列出它并将其映射为servlet。对我来说那是工作。另外,我还可以选择使用下面提到的任何其他功能。所以这对我来说是一件很容易的事。

仅可用于@stateless@singleton

仅可用于@stateless@singleton

启动时通过@startup加载。目前在CDI中没有与此相对应的内容。不知为什么,我们没有在容器生命周期中添加类似afterstartup事件的内容。如果我们这样做了,您就可以有一个@applicationscopedbean来监听它,这实际上与带有@startup@singleton是一样的。它在CDI1.1的列表上。

仅可用于@singleton

@asynchronous方法调用。启动线程在任何服务器端环境中都是禁止的。线程太多是一个严重的性能杀手。这个注释允许您并行化您使用容器的线程池所做的事情。这太棒了。

可用于@statefule@stateless@singleton

@schedulescheduleexpression基本上是cron或quartz功能。也很牛逼。大多数容器只是使用石英在盖子下面的这一点。然而,大多数人并不知道Java EE中的调度工作是事务性的!如果您更新了一个数据库,然后安排了一些工作,但其中一个工作失败,这两个工作都将自动清理。如果EntityManager持久调用失败或刷新出现问题,则不需要取消工作计划。耶,交易。

仅可用于@stateless@singleton

上面关于事务的说明当然要求您使用JTA托管的EntityManager。您可以将它们与普通的“CDI”一起使用,但是如果没有容器管理的事务,它就会得到非常单调的usertransaction提交/回滚逻辑的重复。

可用于所有Java EE组件,包括CDI、JSF@managedbean@webservlet@weblistener@webfilter等。但是,@transactionattribute注释仅可用于@statefule@stateless@singleton

扩展托管EntityManager允许您在JTA事务之间保持EntityManager打开,而不会丢失缓存的数据。天时地利人和的好特点。负责任地使用:)

仅可用于@statefule

当您需要同步时,@lock(READ)@lock(WRITE)注释非常出色。它允许您免费获得并发访问管理。跳过所有ReentrantReadWriteLock管道。在同一桶中的是@accesstimeout,它允许您说明线程在放弃之前应该等待多长时间以获得对bean实例的访问。

仅可用于@singletonbean。

 类似资料:
  • 问题内容: 我看到了一些使用 Promise 访问FB Graph API 的Facebook登录服务的示例。 范例1 : 以及获得响应时使用的服务 范例2 : JSFiddle 问题是: 上面的示例有什么 区别 ? 使用 $ q 服务的 原因 和 案例 是什么? __ 以及它如何 运作 ? 问题答案: 这并不是您问题的完整答案,但是希望当您尝试阅读服务文档时,这将对您和其他人有所帮助。我花了一段

  • 问题内容: 我在某处读到该函数将空字符串视为,因此这不是从HTML表单验证文本输入和文本框的有效方法。 因此,您可以用来检查用户是否键入了某些内容。 函数将空字符串视为是真的吗? 那我应该在什么情况下使用呢?我应该经常检查是否有东西吗? 例如代替 使用这个 问题答案: isset vs.!empty 自由贸易协定: “ isset()检查变量的值是否包含(False,0或空字符串),但不包含NUL

  • 我已经将ViewPager和number of Fragment实现为子级,这里每个子级都覆盖自己的。 在我的应用程序中,导航行为是随机的,不是每次都有顺序。因为页面查看器执行缓存来加载额外的子级,这就是我的问题所在。我不确定何时应该初始化/释放子类成员。 需要你们的建议,在这种情况下使用PageViwer是否更好,或者我应该为每个组件使用传统的活动流。

  • 我正在查看connect文档,而方法或任何描述功能的方法(使用的第三个秘密参数)。我是盲人吗?或者我在哪里可以找到这些信息?

  • 问题内容: 我一直在尝试失败,在Dapper中使用with with子句已经有一段时间了。 在文档中,它确实说支持在a中使用,但我什至无法使它正常工作。 我不断收到的错误消息是Sql语法错误。 我整理了一些测试代码,希望它们能证明我正在尝试实现的目标。 问题答案: 为了执行此处需要的操作,dapper需要即时更改SQL-因此需要 真正 确保它在做正确的事情。常规有效的SQL语法包括括号: 为了消除

  • 问题内容: 我有一个包含和的临时表。它被称为。 我还有另一个包含和的表。它被称为。 我需要获取所有已完成但尚未计划的清单。 因此,我需要以某种方式从已完成的任务中清除所有行,其中都包括: 和 问题答案: 您可以使用以下命令(语法更紧凑): 或版本(尽管更复杂,但使用适当的索引应该会更有效): 当然还有@jmacinnes的答案中的版本。