在JavaEE6中在类级别声明@Resource和@EJB

在JavaEE6中在类级别声明@Resource和@EJB,java,jakarta-ee,ejb-3.0,jndi,Java,Jakarta Ee,Ejb 3.0,Jndi,还有什么情况吗(假设JavaEE6有Java:global/、app/、module/naming) 标准)需要声明EJB或资源,如下面的示例 @EJB (name = "ejb/PlaceBid", beanInterface = PlaceBid.class) public class ActionBazaarBidControllerServlet extends HttpServlet { } 在ActionBazaarBidControllerServlet使用的帮助器类中查找Pl

还有什么情况吗(假设JavaEE6有Java:global/、app/、module/naming) 标准)需要声明EJB或资源,如下面的示例

@EJB (name = "ejb/PlaceBid", beanInterface = PlaceBid.class)
public class ActionBazaarBidControllerServlet extends HttpServlet {

}
ActionBazaarBidControllerServlet使用的帮助器类中查找PlaceBid

PlaceBid placeBid = (PlaceBid)context.lookup("java:comp/env/ejb/PlaceBid");

使用类级注释声明引用和使用java:module、java:app或java:global名称声明引用是截然不同的特性

如果不需要注入但不想使用XML,则可以使用类级注释来声明引用


如果希望模块、应用程序或服务器中的多个组件能够访问同一引用,则可以使用java:module、java:app或java:global名称(无论引用是如何定义的)。例如,您只需要为引用定义一次绑定,而不是为模块(或应用程序或服务器中的所有应用程序)中的每个相同绑定重复相同的绑定信息。

java:comp/env/名称空间有时是一个鲜为人知的特性。该名称空间对应于所谓的
企业命名上下文
(ENC)

它就像一个与每个组件关联的私有“hashmap”,整个web模块被视为一个组件,各个ejbbean也都是组件

您使用这个私有名称空间主要是为了别名的目的。如果在“ejb/PlaceBid”下映射某个内容,那么所有(助手)代码都可以使用“ejb/PlaceBid”,并且在一个全局位置(本例中是servlet,但也可以是XML)可以确定准确映射到它的内容。如果所有代码都直接指向
java:global/..
,那么可能会有几十个与此名称相关的硬编码依赖项

因此,如果您需要额外的重定向,您可以使用它


还有一些需要注意的事项:

一,。 使用EJB SessionContext,您可以直接引用此命名空间,如中所示:

PlaceBid placeBid = (PlaceBid)sessionContext.lookup("ejb/PlaceBid");
这里的“ejb/PlaceBid”是ENC中的相对名称

二,。 如上所述,ENC对于每个组件都是私有的。不同的EJB可以以不同的方式映射给定的相对名称<因此,代码>上下文。查找(“java:comp/env/ejb/PlaceBid”)可以根据调用的组件返回不同的内容

三,。 从历史上看,ENC早于我们现在所说的注入。在某种程度上,当您在XML中指定映射时,您将某些内容“注入”到与该组件关联的私有“hashmap”中。现代版本注入字段、构造函数或属性(setter),而旧版本注入“键”

即使在EJB3.1中,历史上的“注入”机制在引擎盖下仍处于活动状态。如果在字段上使用@EJB执行看似正常的注入,那么这也会自动在JNDI ENC中创建一个条目

package test;

@Stateless
public class MyBean {

   @EJB
   private MyService myService;

}
在本例中,注入myService的内容也存储在ENC中的name
java:comp/env/test.MyBean/myService
下。要使用Servlet上使用的@EJB注释完成链接:您可以选择使用
name
属性指定在ENC中存储引用的名称:

@Stateless
public class MyBean {

   @EJB(name = "ejb/PlaceBid")
   private MyService myService;

}

有点违反直觉,但在大多数情况下,这里的
name
属性并不指向要注入的对象的来源,而是用作ENC中要注入的目标。

为什么要将servlet声明为
@EJB
,要在servlet中使用未被管理(非实体)的helper类吗?我不认为这有什么区别…@Matt类级别的EJB注释没有将servlet声明为“一个EJB”,而是在servlet组件名称空间中声明一个EJB引用@奥努尔,也许你能澄清你所说的“像这样”是什么意思?你的意思是“为什么要在java:comp而不是java:module中声明类级引用”@Matt在bkail中加了一句话:@EJB将PlaceBid引用插入到JNDI中。这种方式使用的注释相当混乱。也许@ENC或@JNDI会更清楚。对于不经意的读者(有时甚至是有经验的读者!)来说,它读起来确实像是将类声明为EJB,但为此使用了注释@Stateless、@Stateful、@Singleton和@MessageDriven。感谢您的透彻解释。@Moro ENC是每个组件的,在EJB的情况下,它是一个bean。@Geek,它只是概念上的一个映射,更正确的说法是一个树或目录。尽管上面示例中的键是“ejb/PlaceBid”,值是“PlaceBid”,但仍被视为一个映射。另一个键可以是“foo”,其值可以是某个数据源。这些变化真是无穷无尽。@Geek>为什么整个web模块被视为一个组件?-这是历史遗留下来的。我不确定现在是否还有人参与JavaEE,知道为什么会做出这个决定。它还有其他一些奇怪的后果,比如ejbjar中定义数据源的方式。请参阅JavaEE规范负责人BillShannon的这篇文章:@Geek>
单个JSF托管bean是否也被以同样的方式对待?据我所知,它们同样由容器管理。
-它们是托管bean,实际上由容器管理,但“托管bean”是一个较新的概念。JavaEE组件名称空间是一个不同且较旧的概念。托管bean不一定是javaee组件(大多数不是),但单个ejbbean既是托管bean又是javaee组件(因此有自己的组件名称空间)。