问题描述
一个不是 EJB 或 CDI 的类(它是一个简单的 java pojo,如示例所示)需要以编程方式查找 RequestScoped bean 的实例。为了防止总是查找同一个实例,我虽然 ThreadLocal
STATIC class aClass {
public static ThreadLocal<RequestScopedBean> aRcBean;
public static Integer getDataFromreqBean() {
if(aRcBean == null) {
aRcBean = new ....
aRcBean.set(CDI.current.select.get(RequestScopedBean.class));
}
return aRcBean.get() != null ? aRcBean.get().doSomething() : null;
}
}
我的问题是,并行请求和线程本地对象不会向 GC 释放实例,我会遇到 GC 和内存泄漏问题吗?
它是我们的一个 java ee jax rs 项目。一个 http 帖子被触发,在我们后端的某个地方我有这个星座。我无法更改太多代码。我需要一个解决方案来像我在上面的例子中提供的那样工作。
解决方法
嗯。假设您的应用程序运行在一些 JavaEE/JacartaEE 应用服务器上,例如 Payara。不是吗?
首先,在我看来,您不需要将代理置于线程本地,您可能更愿意考虑在 POJO 中保留本地接口视图或什至没有接口视图字段。因此,您仍然可以使用上下文查找。
例如。您的无状态 bean:
package stack.overflow.ejb.module.control;
import javax.ejb.Stateless;
/**
*
* @author s.kadakov
*/
@Stateless
public class SomeBean {
public String getBeanName() {
return SomeBean.class.getCanonicalName();
}
}
您的 POJO:
package stack.overflow.ejb.module.control;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
*
* @author s.kadakov
*/
public class SomePojo {
SomeBean someBean = lookupSomeBeanLocal();
public SomeBean getSomeBean() {
return someBean;
}
private SomeBean lookupSomeBeanLocal() {
try {
Context c = new InitialContext();
return (SomeBean) c.lookup("java:global/ejb-module-1.0-SNAPSHOT/SomeBean");
} catch (NamingException ne) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE,"exception caught",ne);
throw new RuntimeException(ne);
}
}
}
提示:您可以在应用程序部署时在应用程序服务器日志中获取您 bean 的可移植 JNDI 名称。就我而言,这些是:
Portable JNDI names for EJB SomeBean: [java:global/ejb-module-1.0-SNAPSHOT/SomeBean,java:global/ejb-module-1.0-SNAPSHOT/SomeBean!stack.overflow.ejb.module.control.SomeBean]]]
您的 JAX-RS 资源:
package stack.overflow.ejb.module.resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import stack.overflow.ejb.module.control.SomePojo;
/**
*
* @author s.kadakov
*/
@Path("javaee8")
public class JavaEE8Resource {
@GET
public Response ping(){
SomePojo pojo = new SomePojo();
String beanName = pojo.getSomeBean().getBeanName();
return Response
.ok(beanName)
.build();
}
}
那么,让我们试试:
curl http://localhost:8080/ejb-module/resources/javaee8
stack.overflow.ejb.module.control.SomeBean
我在 Payara 5 Full 上测试了这个片段,希望它在其他 JavaEE/JakartaEE 兼容服务器上也能以同样的方式工作。
希望它对您有用或为您提供一些提示。