【问题标题】:Declaring @Resource and @EJB at the class level in Java EE6在 Java EE6 的类级别声明 @Resource 和 @EJB
【发布时间】:2011-09-05 00:39:02
【问题描述】:

还有什么情况吗(鉴于Java EE6有java:global/、app/、module/命名 标准)是否需要像下面的示例一样声明 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");

【问题讨论】:

  • 为什么要将 servlet 声明为 @EJB
  • 可能是在 servlet 中使用非托管的辅助类(非实体)?
  • 我不明白这有什么不同...
  • @Matt 类级别的 EJB 注释没有将 servlet 声明为“作为 EJB”,它在 servlet 组件命名空间内声明了一个 EJB 引用。 @Onur,也许您可​​以澄清“像这样”的意思?您的意思是“为什么要在 java:comp 而不是 java:module 中声明类级引用”?
  • @Matt,添加到 bkail:简单地说,@EJB 将 PlaceBid 引用插入到 JNDI 中。以这种方式使用的注释相当混乱。也许@ENC 或@JNDI 会更清楚。对于不经意的读者(有时甚至是有经验的读者!),它确实读起来好像该类被声明为 EJB,但为此使用了注解 @Stateless、@Stateful、@Singleton 和 @MessageDriven。

标签: java jakarta-ee ejb-3.0 jndi


【解决方案1】:

java:comp/env/ 命名空间有时是一个鲜为人知的特性。这个命名空间对应于所谓的Enterprise Naming Context (ENC)。

它就像一个与每个组件关联的私有“哈希图”,整个 Web 模块被视为一个组件,各个 EJB bean 也被视为组件。

您将此私有命名空间主要用于别名处理。如果您在“ejb/PlaceBid”下映射某些内容,那么所有(帮助程序)代码都可以使用“ejb/PlaceBid”并且在一个全局位置(在这种情况下是 servlet,但也可以是 XML),您可以确定准确映射的内容给它。如果所有代码都直接转到java:global/...,那么这个名称可能有几十个硬编码依赖项。

所以,如果你需要额外的重定向,你会使用它。


其他一些注意事项:

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

PlaceBid placeBid = (PlaceBid)sessionContext.lookup("ejb/PlaceBid");

这里的“ejb/PlaceBid”是 ENC 中的相对名称。

2。 如前所述,ENC 对于每个组件都是私有的。不同的 EJB 可以具有不同映射的给定相对名称。 context.lookup("java:comp/env/ejb/PlaceBid") 因此可以返回不同的东西,具体取决于您从哪个组件进行调用。

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

即使在 EJB3.1 中,历史上的“注入”机制在底层仍然有效。如果您在字段上使用@EJB 执行看似正常的注入,那么这也会自动在 JNDI ENC 中创建一个条目。例如

package test;

@Stateless
public class MyBean {

   @EJB
   private MyService myService;

}

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

@Stateless
public class MyBean {

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

}

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

【讨论】:

  • 感谢您的详尽解释。
  • @Moro ENC 是每个组件,在 EJB 的情况下是单个 bean。
  • @Geek,它只是概念上的地图,更准确地说是树或目录。尽管上面示例中的键是“ejb/PlaceBid”,值是“PlaceBid”,但可以看作是一张地图。另一个键可能是“foo”,它的值可能是一些数据源。变化真的无穷无尽。
  • @Geek >为什么将整个 web 模块视为单个组件? - 这是一个历史遗留问题。我不确定这些天是否还有人参与 Java EE 知道为什么会做出这个决定。它还有一些其他奇怪的后果,例如在 ejb-jar 中定义数据源的方式。请参阅 Java EE 规范负责人 Bill Shannon 的这篇文章:java.net/projects/javaee-spec/lists/users/archive/2012-05/…
  • @Geek >individual JSF Managed Beans be also treated the same way? As far as I understand they are similarly managed by the container. - 它们是托管 bean,确实由容器管理,但“托管 bean”是一个较新的概念。 Java EE 组件名称空间是一个不同的旧概念。托管 bean 不一定是 Java EE 组件(大多数不是),但单个 EJB bean 既是托管 bean 又是 Java EE 组件(因此有自己的组件命名空间)。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2017-02-23
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多