@ Inject,@ EJB,@ Local,@ Remote,@ LocalBean等......:困惑?

Bla*_*lin 36 java ejb java-ee cdi

我有以下配置:

  • 1个包含2个带有EJB组件的EJB-JAR的GF上的EAR.
  • 1另一个Glassfish服务器(=>其他JVM)上的WAR 包含访问EJB组件的Web组件.

我在EAR的每个EJB-JAR中都有2个EJB业务服务,它们都是这样开发的:

@Remote
public interface ServiceAItf {
    ...
}

@Stateless
@Local
public class ServiceAImpl implements ServiceAItf {
    ...
}
Run Code Online (Sandbox Code Playgroud)

在我的WAR中,我通过远程接口上的显式"InitialContext.lookup"访问EJB组件.

在我的EAR中,我对注入的最佳实践非常困惑,无论是在性能,架构等方面......

我有以下问题:

  • 如您所见,我已在服务实现上声明了注释"@Local",而没有定义本地接口.这是对的吗?至少我在部署时没有错误.但也许我应该使用"@LocalBean"注释?我想"@LocalBean"注释只是允许直接调用实现作为"本地" EJB,但你必须在代码中使用这样的实现:

    @Stateless @Local public class ServiceBImpl实现ServiceBItf {@EJB private ServiceAImpl serviceA; ...}

  • 将一个EJB注入另一个EJB的最佳方法是什么? 它的工作原理如下:

    @Stateless @Local公共类ServiceBImpl实现ServiceBItf {@EJB private ServiceAItf serviceA; ...}

但是从我注意到的,注入的"serviceA"是远程代理,而它位于同一个EAR文件中的同一个JVM中.所以我认为会对性能产生影响.这就是为什么我试图像这样注入服务:

@Stateless
@Local
public class ServiceBImpl implements ServiceBItf {
    @Inject
    private ServiceAItf serviceA;
    ...
}
Run Code Online (Sandbox Code Playgroud)

但它在GF中不起作用,我有以下例外:

WELD-001408 Unsatisfied dependencies for type [...] ...
Run Code Online (Sandbox Code Playgroud)

然后我尝试创建一个本地接口,并通过注释"@Inject"注入两个服务

即使我创建这样的本地接口,服务也不会通过注释"@Inject"注入,而是为null:

@Local
public interface ServiceALocalItf {
    ...
}
Run Code Online (Sandbox Code Playgroud)

我阅读了很多文章,强烈建议在本地调用时使用"@Inject"而不是"@EJB".这引出了以下问题:在这种情况下,建议(或简单地使用)"@Local" EJB调用?

经过所有这些分析,我得出以下结论:

  • 对于每个服务,我创建一个"@Local"和一个"@Remote"界面.
  • 从WAR到EAR的EJB-JAR,对远程接口进行JNDI查找.
  • 从EJB-JAR到EJB-JAR,通过"@EJB"注入本地接口.
  • 对于同一EJB-JAR中的两个服务,通过"@Inject"向本地接口注入.

你怎么看待这件事?这是对的吗?

jan*_*oth 22

如您所见,我已在服务实现上声明了注释"@Local",而没有定义本地接口.这是对的吗?

使用EJB 3.1,删除了对本地接口的要求.除非您明确需要,否则无需编写它们.

将一个EJB注入另一个EJB的最佳方法是什么?

在这里写几件事情:

使用Java EE 6,Java Enterprise已发生变化.新的JSR定义了一个所谓的托管bean(不要与JSF托管bean混淆)作为一种最小的组件,在依赖注入和生命周期管理方面仍然可以从容器中受益.这意味着:如果您有一个组件并且"只是"想要使用DI并让容器控制其生命周期,则不需要使用EJB.如果 - 并且仅当 - 您明确需要EJB功能(如事务处理,池化,钝化和群集),您将最终使用EJB.

这使得您的问题的答案分为三个部分:

  1. 在@EJB上使用@Inject,CDI(a)的概念适用于所有托管bean(包括EJB)和(b)是有状态的,因此远优于纯@EJB DI
  2. 您确定需要为组件提供EJB吗?
  3. 看一下CDI 文档绝对值得


mak*_*aks -1

@Inject注释用于java bean(POJO),而@EJB注释用于企业java bean。当容器将注释提供的 ejb 注入@EJB到另一个 bean 时,它还控制该 ejb 的生命周期,对无状态 bean 执行池化等(当要注入的 bean 未部署时,引用将为 null)。如果您使用@Inject注释 CDI 机制,只需像使用 new 运算符一样查找并创建注入资源的实例(如果要注入的接口的实现不存在,则引用将为 null)。您可以使用带@Inject注释的限定符来选择注入接口的不同实现。

  • maks - 很抱歉投了反对票,但你的措辞即使不是错误的,也具有误导性。@Inject **不适用于** POJO,它适用于 **ManagedBean**s (JSR 316) 并且**控制生命周期**。ManagedBeans 的实例化与调用 new 运算符有很大不同 - 您缺少 CDI 的整个上下文部分(每个 ManagedBean 驻留在上下文中,因此其生命周期绑定到上下文的生命周期)... (9认同)