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

原因是,我需要在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处于活动状态,每种类型均通过其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)。
这使我可以在同一页面上同时显示n个模型(TestBean)的1视图(test.jsf),例如我的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”。

最佳答案

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

由于无法扩展ManagedBeanBuilder,我决定创建自己的BeanManager(MyBeanManager)。它的行为与com.sun.faces.mgbean.BeanManager的getBeanFromScope和create方法相同,但在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());
}

07-24 21:50