我想扩展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());
}