我想扩展 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)。
这允许我在 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显示名称“Your userId is 27”,包含的test.xhtml的outputText显示“Your userId is 33" 。
答案 0 :(得分:0)
我的解决方案如下(不完全是我想要的,但直到现在我还没有找到更好的方法):
由于我无法扩展 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 < / em>而不是 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());
}