java - 如何扩展 com.sun.jsf.mgbean.ManagedBeanBuilder

标签 java jsf jsf-2 managed-bean

我想扩展com.sun.jsf.mgbean.ManagedBeanBuilder。我必须在哪里注册这样的类(class)?

原因是,我需要在 PostConstruct 之前在要创建的 bean 中设置一个值(基于正在创建的 bean)。所以我必须改变 com.sun.faces.mgbean.BeanBuilder.build方法:

public Object build(InjectionProvider injectionProvider, FacesContext context) {
  Object bean = newBeanInstance();
  injectResources(bean, injectionProvider);
  buildBean(bean, context);
  if (bean instanceof SomeInterface == false) {
    invokePostConstruct(bean, injectionProvider);
  }
  return bean;
}

..随后在MyManagedBeanELResolver的revoleBean(在faces-config.xml中注册为el-resolver)方法中:

result = manager.create(beanName, builder, facesContext);
if (result instanceof SomeInterface) {
  ((SomeInterface) result).setValue(...)
  builder.invoktePostConstruct(result);
}

有更好的解决办法吗?

更新为什么我不能使用kolossus提出的PhaseListener
我无法使用 viewId 来获取 ManagedBean,因为我希望当前有 n 种类型的 Bean 当前处于 Activity 状态,每个类型都通过其 Bean 名称进行访问。

viewId 和 ManagedBean 之间有 1:n 关系,例如我有一个 test.jsf,它有支持 bean TestBean。也可能存在 TestBean0 ,它是 TestBean 的副本,但具有不同的值(我需要注入(inject)它,例如“userId”) 。我的 test.jsf (与 ControllerBean 一起)能够确定应该访问哪个 ManagedBean,TestBeanTestBean0,它显示来自 TestBean 的内容(例如 userId=27)或 *TestBean_0*(例如 userId=33)。
这允许我将 1 View (test.jsf) 与 n 个模型 (TestBean) 显示在同时同一页面,例如我的 test.html 看起来像这样。

....
<h:outputText value="#{controllerBean.getBean('testBean', component).name}" />
<f:subview id="someId">
  <ui:include src="/WEB-INF/templates/test.xhtml" />
</f:subview>
....

因此我可以进行递归(在本例中递归深度为 1),其中 0 级的输出文本显示名称“Your userId is 27”,并且包含的​​ test.xhtml 的输出文本显示“Your userId is 33 英寸。

最佳答案

我的解决方案如下(不完全是我想要的,但到目前为止我没有找到更好的方法):

由于我无法扩展 ManagedBeanBuilder,我决定创建自己的 BeanManager (MyBeanManager)。它的行为与 com.sun.faces.mgbean.BeanManagergetBeanFromScopecreate 方法相同,但在 上略有不同getBuilder:

if (getRegisteredBeans() != null) {
  BeanBuilder builder = getRegisteredBeans().get(name);
  if (builder instanceof ManagedBeanBuilder) {
    builder = new MyManagedBeanBuilder(builder.getManagedBeanInfo());
  }
  return builder;
}
return null;

所以我能够注入(inject)MyManagedBeanBuilder并使用上面提出的构造:

public Object build(InjectionProvider injectionProvider,
    FacesContext context) {
  Object bean = newBeanInstance();
  injectResources(bean, injectionProvider);
  buildBean(bean, context);
  if (bean instanceof SomeInterface == false) {
    invokePostConstruct(bean, injectionProvider);
  }
  return bean;
}

..并且为了在将所需值设置到 bean 后调用@PostConstruct,我必须重写invokePostConstruct以使其公开 而不是 protected

public void invokePostConstruct(Object bean, InjectionProvider injectionProvider) {
  try {
    injectionProvider.invokePostConstruct(bean);
  } catch (InjectionProviderException ipe) {
    String message = MessageUtils.getExceptionMessageString(
    MessageUtils.MANAGED_BEAN_INJECTION_ERROR_ID,
    beanInfo.getName());
    throw new ManagedBeanCreationException(message, ipe);
  }
}

..最终在MyManagedBeanELResolver中,我能够将所需的值设置到bean中,而无需之前调用@PostConstruct。在MyManagedBeanELResolver中:

if (result instanceof SomeInterface) {
  ((SomeInterface) result).setValue(value);
  ((MyManagedBeanBuilder) builder).invokePostConstruct(result, getInjectionProvider());
}

关于java - 如何扩展 com.sun.jsf.mgbean.ManagedBeanBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12801668/

相关文章:

java - 在每个菜单项的标签之前,有一些颜色的空间,我想删除颜色

java - @Named bean 与 localhost 同步

jsf - 禁用大型项目​​中的组件

java - 带有列标题的 Primefaces 订单列表

jsf - 在 ui :repeat to update ArrayList of values is not working 中使用 inputText

java - 线程自动名称更改

java - 如何将文件从一台电脑复制到另一台电脑

java - 无法理解如何从适配器将数据插入列表中

具有持久资源的 Java 线程

java - 没有正确计算到 JSF 页面的分页