我打算使用EJBContext
将一些属性从应用程序层(特别是消息驱动的Bean)传递到无法直接注入(inject)或传递参数的持久性生命周期回调(EclipseLink中的 session 监听器,实体生命周期回调等)。 ,并且该回调函数通过JNDI获取EJBContext
。
这似乎可以正常工作,但是我是否缺少任何隐藏的陷阱,例如线程安全性或对象生命周期? (假设要传递的属性值是不变的,如String或Long。)
样例Bean代码
@MessageDriven
public class MDB implements MessageListener {
private @Resource MessageDrivenContext context;
public void onMessage(Message m) {
context.getContextData().put("property", "value");
}
}
然后使用EJBContext的回调
public void callback() {
InitialContext ic = new InitialContext();
EJBContext context = (EJBContext) ic.lookup("java:comp/EJBContext");
String value = (String) context.getContextData().get("property");
}
我想知道的是,我可以确定
contextData
映射内容仅对当前调用/线程可见吗?换句话说,如果两个线程同时运行callback
方法,并且都从JNDI查找EJBContext
,那么它们实际上得到的是不同的contextData
映射内容吗?而且,这实际上是如何工作的-从JNDI查找返回的
EJBContext
最终是否真的是一个类似于ThreadLocal
的结构的包装对象? 最佳答案
我认为一般而言,该方法的约定是启用拦截器+ Web服务上下文与Bean之间的通信。因此,只要没有创建新的调用上下文,该上下文应可用于所有代码。因此,它应该绝对是线程安全的。
EJB 3.1规范的第12.6节指出:
此外,在4.3.3中描述了getContextData方法:
在实际实现方面,JBoss AS执行以下操作:
public Map<String, Object> getContextData() {
return CurrentInvocationContext.get().getContextData();
}
其中
CurrentInvocationContext
使用基于thread-local linked list的堆栈来弹出并推送当前调用上下文。参见org.jboss.ejb3.context.CurrentInvocationContext。调用上下文只是懒惰地创建了一个简单的
HashMap
,就像org.jboss.ejb3.interceptor.InvocationContextImpl一样Glassfish做类似的事情。它还gets an invocation,并执行from an invocation manager,它也使用基于thread-local array list的堆栈再次弹出并推送这些调用上下文。
GlassFish实现的JavaDoc在这里特别有趣:
就像在JBoss AS中一样,GlassFish也懒惰地创建了一个简单的
HashMap
,在本例中是com.sun.ejb.EjbInvocation。在GlassFish案例中,有趣的是Web服务连接更容易在源中发现。