在另一个视图范围的bean中注入一个视图范围的bean会导致它被重新创建 [英] Injecting one view scoped bean in another view scoped bean causes it to be recreated

查看:144
本文介绍了在另一个视图范围的bean中注入一个视图范围的bean会导致它被重新创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在其他视图范围的bean中使用保存在视图范围bean中的一些数据。

I need to use some data saved in a view scoped bean in an other view scoped bean.

@ManagedBean
@ViewScoped
public class Attivita implements Serializable {
    //
}

@ManagedBean
@ViewScoped
public class Nota implements Serializable {

    @ManagedProperty("#{attivita}")
    private Attivita attivita;

    // Getter and setter.
}

现在,也许我的理论依然很差,我注意到当注入#{attivita} 时,调用 Attivita 构造函数,从而创建另一个实例。这是正确的行为吗?如果我想引用同一个实例,而不是创建一个新的实例呢?

Now, maybe my theory about it is still quite poor, I have noticed that when #{attivita} is injected, the Attivita constructor is invoked and thus creating another instance. Is it the right behaviour? What about if I want to reference the same instance and not create a new one?

推荐答案

如果您导航从一个到另一个观点在回发。视图范围的bean不是绑定到一个请求,而是一个视图。所以当你导航到一个新的视图,它会得到一个全新的视图范围的bean实例。它不会重复使用与先前视图相关联的同一个bean实例。

This will happen if you're navigating from one to the other view on a postback. A view scoped bean is not tied to a request, but to a view. So when you navigate to a new view, it will get a brand new instance of the view scoped bean. It won't reuse the same bean instance which is associated with a previous view.

我明白, attivita bean是在初始视图中创建的,并在回发上重用。我明白 nota bean与您要导航到的新视图相关联。当注入 attivita 时,即使在同一个请求中还有另一个实例,它将简单地获取一个新的和不同的实例。这一切都是预期的(并且确实有点不直观)行为。

I understand that the attivita bean is created on the initial view and reused on postback. I understand that nota bean is associated with the new view where you're navigating to. When injecting attivita in it, it will simply get a new and distinct instance even though there's another instance in the very same request. This is all expected (and admittedly a bit unintuitive) behaviour.

没有标准的JSF解决方案。 CDI通过 @ConversationScoped 来解决这个问题(只要你明确告诉它存在,bean就会生活),而CDI扩展MyFaces CODI在 @ViewAccessScoped (只要导航视图引用它就可以生活)。

There is no standard JSF solution for this. CDI solves this with @ConversationScoped (the bean lives as long as you explicitly tell it to live) and the CDI extension MyFaces CODI goes a bit further with @ViewAccessScoped (the bean lives as long as the navigated view references it).

然而,您可以通过将bean存储为属性来解决此问题在请求范围内。

You could however workaround this by storing the bean as an attribute in the request scope.

@ManagedBean
@ViewScoped
public class Attivita implements Serializable {

    public String submit() {
        FacesContext.getCurrentInstance().getExternalContext()
            .getRequestMap().put("attivita", this);
        return "nota";
    }

}

@ManagedBean
@ViewScoped
public class Nota implements Serializable {

    private Attivita attivita;

    @PostConstruct
    public void init() {
        attivita = (Attivita) FacesContext.getCurrentInstance().getExternalContext()
            .getRequestMap().get("attivita");
    }

}

请注意,这是相当麻烦的。根据具体的功能要求,可能会有更好的解决方案。另请注意,您应该在 nota 视图中将所需的 Attivita bean实例引用为#{ nota.attivita} #{attivita} ,因为它会给你一个新的和不同的实例,原因已经解释过。

Note that this is rather hacky. There may be better solutions depending on the concrete functional requirement. Also note that you should in the nota view reference the desired Attivita bean instance as #{nota.attivita} and not as #{attivita}, because it would give you a new and different instance, for the reasons already explained before.

这篇关于在另一个视图范围的bean中注入一个视图范围的bean会导致它被重新创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆