SessionScoped Bean的Setter将值设至真实类而非代理类问题求助
我之前在Glassfish 5搭配Weld CDI开发时,也碰到过类似的代理实例属性不同步的坑,结合你的场景,给你几个实用的排查和解决方向:
务必通过getter/setter操作SessionController的user属性
CDI的会话作用域bean是通过代理类(也就是你看到的SessionController$Proxy$_$$_WeldClientProxy)来管理的,直接访问类的字段会绕过代理机制。你需要给SessionController的user属性添加公共的setter方法,然后在LoginController里调用这个setter,而不是直接赋值字段。比如:// SessionController类 @SessionScoped public class SessionController implements Serializable { private User user; public void setUser(User user) { this.user = user; } public User getUser() { return user; } } // LoginController类里的赋值逻辑 sessionController.setUser(validatedUser);直接操作
sessionController.user = user只会修改原始实例的字段,代理类的状态不会同步,自然就会出现null的情况。确认SessionController符合CDI代理要求
要让CDI能生成正确的代理类,你的SessionController需要满足:- 不是final类
- 包含无参构造方法(可以是默认的)
- 所有需要被代理的方法(比如setUser、getUser)不是final方法
如果有final修饰的类或方法,Weld无法生成代理,就会导致状态管理异常。
确保注入的是CDI管理的代理实例
检查LoginController里的SessionController是不是通过@Inject注入的,而不是手动new出来的。手动实例化的对象不属于CDI上下文管理,修改它的属性不会同步到会话中的代理实例。正确的注入方式应该是:@RequestScoped public class LoginController { @Inject private SessionController sessionController; // 登录验证逻辑 public String login(String username, String password) { if ("asd".equals(username) && "asd".equals(password)) { User user = new User(); // 填充user属性 sessionController.setUser(user); return "success"; } return "error"; } }检查依赖版本兼容性
Glassfish 5本身内置了Weld 3.x和CDI API 2.0,如果你手动引入了外部的CDI API或Weld依赖,可能会出现版本冲突。建议移除pom.xml或build.gradle中手动添加的CDI相关依赖,直接使用Glassfish自带的版本,避免代理逻辑出现异常。
另外,还要注意不要在异步线程或者非CDI管理的上下文环境中修改SessionScoped bean的属性,这种情况下代理可能无法正确追踪状态变化。
内容的提问来源于stack exchange,提问作者500 Server error

