16

是否可以自动创建 JSF 托管 bean?

例如,我有几个会话范围的 bean。有时需要在代码中(而不仅仅是在 JSF 中)访问这些实例,这是通过以下方式完成的:

PageBean pageBean = (PageBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("pages");

但是,如果没有访问过调用“#{pages}”的页面,这将解析为 null ...当范围“开始”时,无论如何让 JSF 创建一个 bean?那么在这种情况下,理想情况下,当用户会话开始时,'pages' bean 将立即在会话中实例化?

4

4 回答 4

27

改为使用Application#evaluateExpressionGet()。它会在尚未完成时创建 bean。

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{bean}", Bean.class);

"bean"托管 bean 名称在哪里,并且Bean.class是适当的支持 bean 类。

如有必要,您可以将其包装在辅助方法中,这样就不需要强制转换(JSF 男孩没有利用泛型和Classin 中的参数evaluateExpressionGet):

public static <T> T findBean(String managedBeanName, Class<T> beanClass) {
    FacesContext context = FacesContext.getCurrentInstance();
    return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", beanClass));
}

可以用作:

Bean bean = findBean("bean", Bean.class);

或者没有类型,但有@SuppressWarnings

@SuppressWarnings("unchecked")
public static <T> T findBean(String managedBeanName) {
    FacesContext context = FacesContext.getCurrentInstance();
    return (T) context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", Object.class);
}

可以用作:

Bean bean = findBean("bean");

更新:以上是 JSF 1.2 特有的。这是 JSF 1.1 或更早版本使用当前已弃用 Application#createValueBinding()的方法:

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().createValueBinding("#{bean}").getValue(context);
于 2010-01-12T16:11:07.750 回答
3

这个解决方案怎么样:

public static Object getBean(String beanName)
{          
    Object returnObject = FacesContext.getCurrentInstance().getELContext().getELResolver().getValue(FacesContext.getCurrentInstance().getELContext(), null, beanName);  
    if (returnObject == null)  
        System.out.println("Bean with name " + beanName + " was not found. Check the faces-config.xml file if the given bean name is ok.");          
    return returnObject;
}

通过这种方式,您甚至可以避免 Bean.class 参数。

于 2011-05-07T00:03:08.970 回答
0

问:会用

FacesContext 上下文 = FacesContext.getCurrentInstance();

Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{bean}", Bean.class);

每次代码运行这些语句时都会实例化一个新的 Bean?或者它会简单地引用最初创建的同一个实例?

于 2010-12-06T22:41:22.093 回答
0

一种机制是将 bean 注入您想要引用到另一个 bean 的 bean 中,如下所示expensiveBean

  <managed-bean>
    <managed-bean-name>requestBean</managed-bean-name>
    <managed-bean-class>lifetime.RequestBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
      <property-name>cachedAsset</property-name>
      <property-class>lifetime.ExpensiveBean</property-class>
      <value>#{expensiveBean}</value>
    </managed-property>
  </managed-bean>

这不是很“懒惰”,但它可以很方便。

于 2010-01-12T16:13:47.957 回答