1

我想扩展com.sun.jsf.mgbean.ManagedBeanBuilder。我必须在哪里注册这样的课程?

原因是,我需要在 PostConstruct 之前的 bean-to-create 中设置一个值(基于正在创建的 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 当前处于活动状态,每种类型都通过它们的 bean 名称访问。

我在 viewId 和 ManagedBean 之间有 1:n 的关系,例如,我有一个test.jsf,它具有支持 bean TestBean。也有可能存在一个TestBean0 ,它是一个TestBean的副本,但具有不同的值(我需要注入它,例如“userId”)。我的test.jsf(与ControllerBean一起能够确定应该访问哪个 ManagedBean,无论是TestBean还是TestBean0,它显示来自TestBean的内容(例如 userId=27)或 *TestBean_0* (例如 userId=33)。
这允许我有1 个视图(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 的 outputText 显示名称“您的 userId 为 27”,包含的 test.xhtml 的 outputText 显示“您的 userId 为 33”。

4

1 回答 1

0

我的解决方案如下(不完全是我想要的,但直到现在我还没有找到更好的方法):

由于我无法扩展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;

所以我能够注入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以使其公开而不是受保护

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());
}
于 2013-06-20T07:06:57.747 回答