将 @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 实例。

我看到两个问题:

  1. 你这里的主要问题是你有循环依赖。尽量避免这种情况。 ViewScopedBean 不能依赖于 SessionScopedBean ,反之亦然,因为 CDI 不知道先创建哪个。 (这就是为什么您必须在 @PostConstruct 方法中手动设置依赖项的原因。)
  2. 您不能通过比较它们的引用来比较 Bean,因为它们被序列化/反序列化,因此不是相同的对象。这就是为什么您应该使用 equals() 比较它们并实施 hashCode() 方法。