多远程EJB接口:如何使不同远程接口指向同一有状态EJB实例?
如何让两个远程接口指向同一个有状态EJB实例
当然可以实现!核心思路是**复用同一个会话上下文(Session Context)**来获取第二个接口的引用,而不是重新通过JNDI查找或依赖注入创建新实例。下面给你几种可行的实现方式:
方法一:通过EJB上下文的getBusinessObject()方法获取同实例的另一个接口引用
这是跨容器兼容的标准做法,在你的有状态EJB实现类中注入SessionContext,然后提供一个方法返回另一个接口的实例:
import javax.ejb.Stateful; import javax.ejb.SessionContext; import javax.annotation.Resource; @Stateful public class MyStatefulBean implements Interface1, Interface2 { @Resource private SessionContext sessionContext; private int counter = 0; // Interface1的方法 @Override public void increment() { counter++; } // Interface2的方法 @Override public int getCounter() { return counter; } // 提供获取同实例Interface2引用的方法 public Interface2 getInterface2Reference() { return sessionContext.getBusinessObject(Interface2.class); } }
客户端操作流程:先获取Interface1实例并调用increment(),再通过该实例调用getInterface2Reference()拿到同实例的Interface2,最后调用getCounter()就能得到1。
方法二:客户端通过JNDI查找时指定同一个会话ID
部分EJB容器支持在JNDI查找时传递会话ID参数,关联到已有的有状态实例(注意:这种方式依赖具体容器实现,通用性稍弱)。
以WildFly为例,代码大致如下:
// 先获取Interface1实例并执行操作 Interface1 interface1 = (Interface1) context.lookup("java:global/MyApp/MyStatefulBean!com.example.Interface1"); interface1.increment(); // 提取已有实例的会话ID Handle handle = ((EJBObject) interface1).getHandle(); String sessionId = ...; // 具体解析逻辑依容器而定 // 携带会话ID查找Interface2 Hashtable<String, Object> env = new Hashtable<>(); env.put("org.jboss.ejb.client.session-id", sessionId); Context newContext = new InitialContext(env); Interface2 interface2 = (Interface2) newContext.lookup("java:global/MyApp/MyStatefulBean!com.example.Interface2"); System.out.println(interface2.getCounter()); // 输出1
方法三:合并接口(业务允许时可选)
如果业务逻辑允许,可以定义一个包含两个接口所有方法的超接口,让EJB实现这个超接口。客户端只需获取一次超接口实例,就能调用两个接口的所有方法,自然是同一个实例。不过这种方式会改变原有接口设计,需要根据实际场景评估是否合适。
需要注意:有状态EJB的实例和客户端会话绑定,必须确保在同一个客户端会话内复用实例引用,不能让容器创建新实例。优先推荐第一种标准实现方式。
内容的提问来源于stack exchange,提问作者user9222777
相关产品推荐
相关产品推荐

