我正在制作一个基于Java EE的产品,其中我使用了GlassFish 3和EJB 3.1。
我的应用程序有会话bean,一个调度程序,并且使用web服务。我最近了解了Apache TomEE,它支持上下文和依赖注入(CDI)。GlassFish容器也支持CDI。
如果我不需要CDI也不提供的任何特性,我可以替换会话bean吗?如果那样的话,我能得到什么好处呢?
是的,您可以自由地混合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。@statefule
bean还可以使用上述任何一个作用域注释,从而使它与作用域中的所有其他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
事件的内容。如果我们这样做了,您就可以有一个@applicationscoped
bean来监听它,这实际上与带有@startup
的@singleton
是一样的。它在CDI1.1的列表上。
仅可用于@singleton
。
@asynchronous
方法调用。启动线程在任何服务器端环境中都是禁止的。线程太多是一个严重的性能杀手。这个注释允许您并行化您使用容器的线程池所做的事情。这太棒了。
可用于@statefule
、@stateless
和@singleton
。
@schedule
或scheduleexpression
基本上是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实例的访问。
仅可用于@singleton
bean。
问题内容: 我看到了一些使用 Promise 访问FB Graph API 的Facebook登录服务的示例。 范例1 : 以及获得响应时使用的服务 范例2 : JSFiddle 问题是: 上面的示例有什么 区别 ? 使用 $ q 服务的 原因 和 案例 是什么? __ 以及它如何 运作 ? 问题答案: 这并不是您问题的完整答案,但是希望当您尝试阅读服务文档时,这将对您和其他人有所帮助。我花了一段
问题内容: 我在某处读到该函数将空字符串视为,因此这不是从HTML表单验证文本输入和文本框的有效方法。 因此,您可以用来检查用户是否键入了某些内容。 函数将空字符串视为是真的吗? 那我应该在什么情况下使用呢?我应该经常检查是否有东西吗? 例如代替 使用这个 问题答案: isset vs.!empty 自由贸易协定: “ isset()检查变量的值是否包含(False,0或空字符串),但不包含NUL
我正在查看connect文档,而方法或任何描述功能的方法(使用的第三个秘密参数)。我是盲人吗?或者我在哪里可以找到这些信息?
我已经将ViewPager和number of Fragment实现为子级,这里每个子级都覆盖自己的。 在我的应用程序中,导航行为是随机的,不是每次都有顺序。因为页面查看器执行缓存来加载额外的子级,这就是我的问题所在。我不确定何时应该初始化/释放子类成员。 需要你们的建议,在这种情况下使用PageViwer是否更好,或者我应该为每个组件使用传统的活动流。
问题内容: 我一直在尝试失败,在Dapper中使用with with子句已经有一段时间了。 在文档中,它确实说支持在a中使用,但我什至无法使它正常工作。 我不断收到的错误消息是Sql语法错误。 我整理了一些测试代码,希望它们能证明我正在尝试实现的目标。 问题答案: 为了执行此处需要的操作,dapper需要即时更改SQL-因此需要 真正 确保它在做正确的事情。常规有效的SQL语法包括括号: 为了消除
问题内容: 我有一个包含和的临时表。它被称为。 我还有另一个包含和的表。它被称为。 我需要获取所有已完成但尚未计划的清单。 因此,我需要以某种方式从已完成的任务中清除所有行,其中都包括: 和 问题答案: 您可以使用以下命令(语法更紧凑): 或版本(尽管更复杂,但使用适当的索引应该会更有效): 当然还有@jmacinnes的答案中的版本。