Jsf 将视图范围的bean注入另一个视图范围的bean

Jsf 将视图范围的bean注入另一个视图范围的bean,jsf,managed-bean,jsf-2.2,Jsf,Managed Bean,Jsf 2.2,只要用户与同一个视图交互(或者导航到不同的视图),视图范围的bean就保持活动状态 假设一个视图范围的托管bean被注入另一个视图范围的bean,如下所示 @ManagedBean @ViewScoped public final class SharableManagedBean implements Serializable { private static final long serialVersionUID = 1L; @EJB private Sharabl

只要用户与同一个视图交互(或者导航到不同的视图),视图范围的bean就保持活动状态

假设一个视图范围的托管bean被注入另一个视图范围的bean,如下所示

@ManagedBean
@ViewScoped
public final class SharableManagedBean implements Serializable
{
    private static final long serialVersionUID = 1L;

    @EJB
    private SharableBean sharableService;

    //...Do something.
}

@ManagedBean
@ViewScoped
public final class TestManagedBean implements Serializable
{
    private static final long serialVersionUID = 1L;

    @EJB
    private TestBean testBean;

    @ManagedProperty(value="#{sharableManagedBean}")
    private SharableManagedBean sharableManagedBean ;

    //... Do something with the injected bean.
}
在这种情况下,
shalablemanagedbean
是否需要一个视图范围的bean


如果它是请求范围的bean(
SharableManagedBean
),会发生什么?当
TestManagedBean
出现并销毁时,当
TestManagedBean
销毁时,它是否只初始化一次?

即使在技术上也可以这样做(JSF允许您注入范围相同或更广的bean)我看不出用
@ViewScoped
bean这样做有什么意义。在我看来,一个设计良好的JSF web应用程序应该有一个绑定到每个特定视图的
@ViewScoped
bean。那么,如何解决你的问题呢?您可以通过两种方式完成:

  • 如果
    SharableManagedBean
    是一个实用程序bean,它包含不与JSF绑定的静态方法,只需将这个类定义为
    abstract
    ,并在需要时静态调用它的方法
  • 如果
    SharableManagedBean
    本身必须是一个访问的托管bean,并且具有所有视图bean共享的公共代码,那么只需创建一个
    abstract
    类,并使您的
    @ViewScoped
    bean扩展它
  • 对于您的最后一个问题(
    shalablemanagedbean
    being
    @RequestScoped
    ),JSF不允许您这样做。由于尝试注入范围更窄的托管bean,您将得到一个异常

    根据报告:

    关于托管bean相互引用的另一个重要问题是,托管bean只能引用其他bean,前提是它们的作用域与调用对象相等或具有更长的生命周期

    更新


    如果使用CDI,也可以使用代理模式将
    @RequestScoped
    bean注入
    @ViewScoped
    bean。拥有。

    是有道理的。谢谢:)。(我今天没有投票,明天就可以了。)通过CDI管理bean时,在视图范围bean中注入请求范围bean是有效的。您只需要记住,这实际上注入了一个代理,它在方法调用中为您返回当前实例,因此在postconstruct和后续表单提交期间,它不一定是同一个实例(因此,您需要手动复制postconstruct中的必要属性,如果有的话)实际上并不知道这一点。我不使用CDI,所以我需要看一看;-)