Java 在@modelbean中注入的EJB在每次请求时都会被创建(GlassFish)

Java 在@modelbean中注入的EJB在每次请求时都会被创建(GlassFish),java,jsf,glassfish,ejb,cdi,Java,Jsf,Glassfish,Ejb,Cdi,我在网上找不到这个问题的答案或任何参考资料。问题就在这里 我有一个非常简单的网络项目 index.xhtml 指数 MyBean.java import javax.enterprise.inject.Model; import javax.inject.Inject; @Model public class MyBean { @Inject private MyEJB myEjb; public

我在网上找不到这个问题的答案或任何参考资料。问题就在这里

我有一个非常简单的网络项目

  • index.xhtml
指数

  • MyBean.java

import javax.enterprise.inject.Model; import javax.inject.Inject; @Model public class MyBean { @Inject private MyEJB myEjb; public MyBean() { System.out.println("Creating MyBean"); } private String name; private String message; public void sayHello() { setMessage(myEjb.sayHello(getName())); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getName() { return name; } public void setName(String name) { this.name = name; } } import javax.ejb.EJB; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @RequestScoped @ManagedBean public class MyBean { @EJB private MyEJB myEjb; public MyBean() { System.out.println("Creating MyBean"); } private String name; private String message; public void sayHello() { setMessage(myEjb.sayHello(getName())); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 导入javax.enterprise.inject.Model; 导入javax.inject.inject; @模型 公共类MyBean { @注入 私人医院; 公共MyBean() { System.out.println(“创建MyBean”); } 私有字符串名称; 私有字符串消息; 公共空间 { setMessage(myEjb.sayHello(getName()); } 公共字符串getMessage() { 返回消息; } 公共无效设置消息(字符串消息) { this.message=消息; } 公共字符串getName() { 返回名称; } 公共void集合名(字符串名) { this.name=名称; } }

  • MyEJB.java

import javax.ejb.Stateless; @Stateless public class MyEJB { public MyEJB() { System.out.println("Creating MyEJB"); } public String sayHello(String name) { return "Hello " + name; } } 导入javax.ejb.Stateless; @无国籍 公共类 { 公共图书馆 { System.out.println(“创建MyEJB”); } 公共字符串sayHello(字符串名称) { 返回“Hello”+name; } }

这是正确的,但glassfish日志显示了这一点

Información:创建MyBean Información:创建MyBean Información:创建MyEJB Información:创建MyBean Información:创建MyEJB Información:创建MyEJB

只要一个请求

这意味着MyBean在请求中被创建了3次,MyEJB被创建了3次以上

我不知道这是一种正常的行为,还是glassfish上的一个bug,或者我在这里做了一些非常错误的事情,因为如果每个请求都创建和销毁了这么多对象,seriuos应用程序就会出现问题

如果我换成这样一个更经典的套路

import javax.enterprise.inject.Model; import javax.inject.Inject; @Model public class MyBean { @Inject private MyEJB myEjb; public MyBean() { System.out.println("Creating MyBean"); } private String name; private String message; public void sayHello() { setMessage(myEjb.sayHello(getName())); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getName() { return name; } public void setName(String name) { this.name = name; } } import javax.ejb.EJB; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @RequestScoped @ManagedBean public class MyBean { @EJB private MyEJB myEjb; public MyBean() { System.out.println("Creating MyBean"); } private String name; private String message; public void sayHello() { setMessage(myEjb.sayHello(getName())); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 导入javax.ejb.ejb; 导入javax.faces.bean.ManagedBean; 导入javax.faces.bean.RequestScope; @请求范围 @ManagedBean 公共类MyBean { @EJB 私人医院; 公共MyBean() { System.out.println(“创建MyBean”); } 私有字符串名称; 私有字符串消息; 公共空间 { setMessage(myEjb.sayHello(getName()); } 公共字符串getMessage() { 返回消息; } 公共无效设置消息(字符串消息) { this.message=消息; } 公共字符串getName() { 返回名称; } 公共void集合名(字符串名) { this.name=名称; } }

输出是不同的

我创建了1个ejb,然后请求的其余部分由该实例处理 对于每个请求,MyBean都会创建一次

请帮助我,也许我误解了cdi规范


感谢调试EJB/CDI/JSF/的构造函数。。。他是个假朋友

在现代框架中,有很多事情在幕后进行——其中相当一部分是使用Java反射的——并且您不能依赖对构造函数的调用来指示您有一个新的、随时可用的组件

您需要做的是使用一个适当的生命周期挂钩。它们被明确设计为在创建/销毁/解除钝化/钝化组件之后/之前调用


在您的情况下,使用
@PostConstruct
,.

调试EJB/CDI/JSF/的构造函数。。。他是个假朋友

在现代框架中,有很多事情在幕后进行——其中相当一部分是使用Java反射的——并且您不能依赖对构造函数的调用来指示您有一个新的、随时可用的组件

您需要做的是使用一个适当的生命周期挂钩。它们被明确设计为在创建/销毁/解除钝化/钝化组件之后/之前调用


在您的情况下,请使用
@PostConstruct

好的,很抱歉,首先它没有创建bean 3次,每个请求一次,我在浏览器上预告了f5,我通过添加@Named来解决EJB创建问题。但是我在我读过的任何cdi教程中都没有看到这个要求,所以我不明白第二个代码示例中没有什么“经典的”。第一个使用CDI进行注入,第二个使用JSF和EJB进行注入,这是两种截然不同的模型@模型是RequestScope和Named的CDI版本的快捷方式。是的,您的模型对象将被创建多次。好的,很抱歉,首先它没有创建bean 3次,每个请求一次,我在浏览器上使用了f5,我通过添加@Named来解决EJB创建问题。但是我在我读过的任何cdi教程中都没有看到这个要求,所以我不明白第二个代码示例中没有什么“经典的”。第一个使用CDI进行注入,第二个使用JSF和EJB进行注入,这是两种截然不同的模型@模型是RequestScope和Named的CDI版本的快捷方式。因此,您的模型对象将被多次创建。