You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

@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();
    }
}

原因分析与解决方案

核心问题

你遇到的情况源于两个关键规则:

  1. JAX-RS资源类的默认作用域:Services作为JAX-RS资源类,默认是请求作用域——容器会为每一次HTTP请求创建一个全新的Services实例。
  2. Stateful Bean的绑定逻辑:当在请求作用域的组件中注入@Stateful Bean时,容器会为每个新的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:05:19