我有以下配置:
- 一个包含2个EJB组件的EAR文件,存储在一个GF服务器上。
- 一个WAR文件,存储在另一个Glassfish服务器上(=>不同JVM),其中包含访问EJB组件的Web组件。
我的EAR中每个EJB-JAR都有2个EJB业务服务,并且它们都是这样开发的:
@Remote
public interface ServiceAItf {
...
}
@Stateless
@Local
public class ServiceAImpl implements ServiceAItf {
...
}
在我的WAR文件中,我通过对远程接口的显式"InitialContext.lookup"进行访问EJB组件。
在我的EAR文件中,关于注入最佳实践方面,我感到非常困惑,例如性能、架构等等...
我有以下问题:
正如您所看到的,我在服务实现中声明了注释"@Local",但没有定义本地接口。这是正确的吗?至少我在部署时没有错误。但也许我应该使用"@LocalBean"注释?我认为"@LocalBean"注释简单地允许直接调用实现作为"Local" EJB,但您必须像这样在代码中使用实现:
@Stateless @Local public class ServiceBImpl implements ServiceBItf { @EJB private ServiceAImpl serviceA; ... }
注入一个EJB到另一个EJB的最佳方式是什么? 它的工作方式如下:
@Stateless @Local public class ServiceBImpl implements ServiceBItf { @EJB private ServiceAItf serviceA; ... }
但是从我注意到的情况来看,注入的“serviceA”是远程代理,而它在同一个JVM中,位于同一个EAR文件中。所以我认为这将会对性能产生影响。这就是为什么我尝试像这样注入服务:
@Stateless
@Local
public class ServiceBImpl implements ServiceBItf {
@Inject
private ServiceAItf serviceA;
...
}
但是在GF中它不起作用,我遇到了以下异常:
WELD-001408 Unsatisfied dependencies for type [...] ...
我尝试创建一个本地接口,使用注解“@Inject”进行的依赖注入在两个服务都存在时可以正常工作。
即使我像这样创建本地接口,该服务也无法通过注解“@Inject”进行依赖注入,而是为null:
@Local
public interface ServiceALocalItf {
...
}
我阅读了很多文章,高度推荐在本地调用时使用 "@Inject" 而不是 "@EJB"。这引发了我以下的问题:在哪种情况下建议(或仅仅使用)"@Local" EJB 呼叫?
经过所有这些分析,我得出以下结论:
- 对于每个服务,我创建一个"@Local"和一个"@Remote"接口。
- 从 WAR 到 EAR 的 EJB-JAR,使用 JNDI 查找远程接口。
- 从 EJB-JAR 到 EJB-JAR,通过"@EJB"注入到本地接口。
- 对于同一 EJB-JAR 中的两个服务,通过"@Inject"注入到本地接口。
你认为怎么样?它正确吗?