JSF Управляемый Bean автосоздание?
Можно ли автоматически создать управляемый JSF bean?
Например, у меня есть несколько сеансов beans. Иногда возникает необходимость доступа к этим экземплярам в коде (а не только в JSF), это делается с помощью:
PageBean pageBean = (PageBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("pages");
Однако, если ни одна страница не была посещена, которая вызывает "# {pages}", это разрешает null... есть ли все-таки, чтобы JSF создавал bean, когда область "начинается"? Итак, в этом случае в идеале, когда начинается сеанс пользователя, "страницы" bean будут немедленно созданы в сеансе?
Ответы
Ответ 1
Используйте Application#evaluateExpressionGet()
. Он будет создавать bean, если еще не выполнен.
FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{bean}", Bean.class);
Где "bean"
- управляемое имя bean, а Bean.class
- соответствующий класс bean.
Вы можете в случае необходимости обернуть это в вспомогательный метод, чтобы кастинг был ненужным (мальчики JSF не использовали преимущества дженериков и параметр Class
в 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);
Ответ 2
Как насчет этого решения:
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.
Ответ 3
Один из механизмов заключается в том, чтобы вставить 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>
Это не очень "ленивый", но это может быть удобно.
Ответ 4
Вопрос: будет использовать
FacesContext context = FacesContext.getCurrentInstance();
Bean Bean= (Bean) context.getApplication(). evaluateExpressionGet (контекст, "# { bean}", Bean.class);
вызывать новый экземпляр Bean каждый раз, когда код проходит через эти инструкции? Или он просто ссылается на тот же самый экземпляр, который был изначально создан?