1

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を使用できない理由を更新します。現在アクティブなn種類のBeanがあり、それぞれがBean名でアクセスされる
ため、viewIdを使用してManagedBeanをフェッチできません。

viewIdとManagedBeanの間に1:nの関係があります。たとえば、backing-beanTestBeanを持つtest.jsfあります。TestBean0が存在する可能性もあります。これは、たとえばTestBeanのコピーですが、値が異なります(たとえば、「userId」を挿入する必要があります)。私のtest.jsf ( ControllerBeanと一緒に、 TestBeanまたはTestBean0のいずれかにアクセスする必要があるManagedBeanを決定できます。これは、 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は「YouruserId is 27」という名前を示し、含まれているtest.xhtmlのoutputTextは「YouruserIdis33」を示します。

4

1 に答える 1

0

私の解決策は次のとおりです(正確には私が望んでいたものではありませんが、今まで私はより良い方法を見つけられませんでした):

ManagedBeanBuilderを拡張できなかったため、独自のBeanManager(MyBeanManager)を作成することにしました。これは、com.sun.faces.mgbean.BeanManagergetBeanFromScopeおよび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で、以前に@PostConstructを呼び出さなくても、目的の値をBeanに設定できました。MyManagedBeanELResolverで:

if (result instanceof SomeInterface) {
  ((SomeInterface) result).setValue(value);
  ((MyManagedBeanBuilder) builder).invokePostConstruct(result, getInjectionProvider());
}
于 2013-06-20T07:06:57.747 に答える