@Stateful注解Bean为何表现反常?实例不一致问题咨询
问题描述
点击测试按钮重复发起请求后,每次获取到的Demo类实例都不一样,但我原本预期会是同一个实例。请问我忽略了哪些关键点?
相关代码如下:
Bean 代码
@Stateful @LocalBean public class Demo { public Demo() { } }
Service 代码
@Path("/") public class Services { @EJB Demo demo; @POST @Produces(MediaType.APPLICATION_JSON) @Path("Testing") public Response testing(){ return Response.ok(demo.hashCode()).build(); } }
原因分析与解决方案
核心问题
你遇到的情况源于两个关键规则:
- JAX-RS资源类的默认作用域:
Services作为JAX-RS资源类,默认是请求作用域——容器会为每一次HTTP请求创建一个全新的Services实例。 - Stateful Bean的绑定逻辑:当在请求作用域的组件中注入
@StatefulBean时,容器会为每个新的Services实例分配一个全新的Demo实例,因为Stateful Bean的生命周期默认会和注入它的宿主组件绑定。
这就导致每次请求都会生成新的Services和对应的Demo实例,所以返回的hashCode每次都不同。
解决方案
根据你的实际需求,有两种常见处理方式:
1. 改为单实例Bean(无需会话状态场景)
如果你只是想要全局唯一的Demo实例,直接把Demo的注解从@Stateful改成@Singleton即可:
@Singleton @LocalBean public class Demo { public Demo() { } }
@Singleton Bean在整个应用生命周期内只会存在一个实例,无论多少请求,注入的都是同一个对象。
2. 绑定Stateful Bean到客户端会话(需保留会话状态场景)
如果你需要同一个客户端的多次请求复用同一个Demo实例(利用Stateful Bean的会话状态特性),可以这样实现:
- 将
Services改为会话作用域(需CDI支持):
@Path("/") @SessionScoped public class Services implements Serializable { @EJB Demo demo; @POST @Produces(MediaType.APPLICATION_JSON) @Path("Testing") public Response testing(){ return Response.ok(demo.hashCode()).build(); } }
- 确保客户端请求时保持会话(多数HTTP客户端默认会通过Cookie维护会话),这样同一个客户端的多次请求会复用同一个
Services实例,进而复用同一个Demo实例。
你也可以手动管理Stateful Bean生命周期:第一次请求时创建Demo实例并存储到HTTP Session,后续请求从Session中直接获取该实例。
内容的提问来源于stack exchange,提问作者Prashant Kumar
相关产品推荐
相关产品推荐

