将 @Named @ViewScoped 注入到 @SessionScoped 中
Inject a @Named @ViewScoped into a @SessionScoped
我有两个 bean 使用 @Named
,一个使用 @SessionScoped
,另一个使用 @ViewScoped
。我可以将 @ViewScoped
bean 注入到 @SessionScoped
中,我尝试做相反的事情,我几乎可以工作,但我没有相同的实例。
当我在视图作用域 bean 的 @PostContruct
方法中打印 this.hashCode()
并将其与会话作用域 bean 中注入的方法进行比较时,我可以看到它。
所以我找到了一个解决方案,但我不知道这是否是一个好的做法:在注入会话作用域 bean 之后,在视图作用域 bean 的 @PostContruct
方法中,我发送视图作用域通过 setter.
进入会话范围
如果我很清楚这些对象与用户相关联,所以不会造成任何麻烦,对吗?
@Named
@ViewScoped
public class ViewScopedBean {
@Inject
protected SessionScopedBean sessionScopedBean;
@PostContruct
public void init() {
sessionScopedBean.setViewScopedBean(this);
}
}
@Named
@SessionScoped
public class SessionScopedBean {
protected ViewScopedBean viewScopedBean;
public void setViewScopedBean(ViewScopedBean viewScopedBean) {
this.viewScopedBean = viewScopedBean;
}
}
将我在评论中写的内容提取为答案:
这里的问题是 CDI/Weld 不直接 @Inject
上下文实例而是移交代理实例(对于 @NormalScoped
bean!),然后委托给一个底层bean 实例;在这种情况下 @ViewScoped
bean.
在问题中假设 hashCode()
可用于注入对象以验证它们是否相同。然而,这不一定是真的,因为 CDI 可以选择为每个注入点提供不同的代理,并且 hashCode()
将在代理对象上调用,而不是底层 bean 实例 - 因此存在差异。
要走的路是检查 bean 的内部状态,这被证明是相等的,因此表明两个注入点都注入了相同的 @viewScoped
bean 实例。
我看到两个问题:
- 你这里的主要问题是你有循环依赖。尽量避免这种情况。
ViewScopedBean
不能依赖于 SessionScopedBean
,反之亦然,因为 CDI 不知道先创建哪个。 (这就是为什么您必须在 @PostConstruct
方法中手动设置依赖项的原因。)
- 您不能通过比较它们的引用来比较 Bean,因为它们被序列化/反序列化,因此不是相同的对象。这就是为什么您应该使用
equals()
比较它们并实施 hashCode()
方法。
我有两个 bean 使用 @Named
,一个使用 @SessionScoped
,另一个使用 @ViewScoped
。我可以将 @ViewScoped
bean 注入到 @SessionScoped
中,我尝试做相反的事情,我几乎可以工作,但我没有相同的实例。
当我在视图作用域 bean 的 @PostContruct
方法中打印 this.hashCode()
并将其与会话作用域 bean 中注入的方法进行比较时,我可以看到它。
所以我找到了一个解决方案,但我不知道这是否是一个好的做法:在注入会话作用域 bean 之后,在视图作用域 bean 的 @PostContruct
方法中,我发送视图作用域通过 setter.
如果我很清楚这些对象与用户相关联,所以不会造成任何麻烦,对吗?
@Named
@ViewScoped
public class ViewScopedBean {
@Inject
protected SessionScopedBean sessionScopedBean;
@PostContruct
public void init() {
sessionScopedBean.setViewScopedBean(this);
}
}
@Named
@SessionScoped
public class SessionScopedBean {
protected ViewScopedBean viewScopedBean;
public void setViewScopedBean(ViewScopedBean viewScopedBean) {
this.viewScopedBean = viewScopedBean;
}
}
将我在评论中写的内容提取为答案:
这里的问题是 CDI/Weld 不直接 @Inject
上下文实例而是移交代理实例(对于 @NormalScoped
bean!),然后委托给一个底层bean 实例;在这种情况下 @ViewScoped
bean.
在问题中假设 hashCode()
可用于注入对象以验证它们是否相同。然而,这不一定是真的,因为 CDI 可以选择为每个注入点提供不同的代理,并且 hashCode()
将在代理对象上调用,而不是底层 bean 实例 - 因此存在差异。
要走的路是检查 bean 的内部状态,这被证明是相等的,因此表明两个注入点都注入了相同的 @viewScoped
bean 实例。
我看到两个问题:
- 你这里的主要问题是你有循环依赖。尽量避免这种情况。
ViewScopedBean
不能依赖于SessionScopedBean
,反之亦然,因为 CDI 不知道先创建哪个。 (这就是为什么您必须在@PostConstruct
方法中手动设置依赖项的原因。) - 您不能通过比较它们的引用来比较 Bean,因为它们被序列化/反序列化,因此不是相同的对象。这就是为什么您应该使用
equals()
比较它们并实施hashCode()
方法。