即使已经实例化了 ManagedBean(例如在 AJAX 调用上),也会调用 @PostConstruct 方法[重复]
Posted
技术标签:
【中文标题】即使已经实例化了 ManagedBean(例如在 AJAX 调用上),也会调用 @PostConstruct 方法[重复]【英文标题】:@PostConstruct method is called even if the ManagedBean has already been instantiated (e.g. on AJAX-calls) [duplicate] 【发布时间】:2012-02-06 22:13:45 【问题描述】:我有一个@ViewScope ManagedBean 和一个@PostConstruct 初始化方法。此方法在创建新实例时调用,但也在每次 ajax 调用时调用。为什么会这样?
在 AJAX 调用中,会调用并执行 init-Method,但看不到任何更改。例如,如果我在 init-Method 中更改了一个属性,这仅在实例化时可见,而对于 AJAX 调用不可见。对于 AJAX 调用,值更改不会在 @ViewScoped Bean 中持久化。
谁能说出为什么会这样?我该如何更改?
【问题讨论】:
@PeterGwiazda 但没有真正回答。 好的。我的评论是一样的:粘贴您的 JSF 页面。看起来视图根已重新创建。例如,当您尝试在 JSF 代码中使用 JSTL(例如 c:if)时,就会发生这种情况。 @PeterGwiazda 我的代码太大,无法粘贴到这里。我将尝试创建一个简短的版本。我在我的所有视图范围的 bean 中都遇到了这种行为。如果有帮助,我还会使用<ui:include>
和 Richfaces。
【参考方案1】:
这不是正常行为。如果在打开部分状态保存时将标记处理程序属性或 JSF 组件的 binding
属性绑定到视图范围 bean 的属性,则会发生这种情况。这被称为issue 1492,已在(即将推出的)Mojarra 2.2 中修复。
通常,您可以通过缺少rendered
属性来识别标记处理程序。例如。 <c:if>
、<f:validator>
、<ui:include>
等。如果将此类标记处理程序的属性绑定到视图范围 bean 的属性,如下所示
<c:if test="#viewScopedBean.something"></c:if>
<h:inputText><f:validator binding="#viewScopedBean.validate" /></h:inputText>
<ui:include src="#viewScopedBean.includePage" />
然后每次从部分保存的状态恢复视图时,都会重新创建视图范围的 bean。这是视图范围的鸡蛋问题,因为为了获得 right 视图范围的 bean,必须从恢复的视图中提取它。
如果您在 JSF 组件的 binding
属性中引用视图范围 bean 的属性,也会发生这种情况。
<h:someComponent binding="#viewScopedBean.someComponent" />
另见:
Communication in JSF 2.0 -@ViewScoped
fails in tag handlers
【讨论】:
非常感谢。情况就是这样。我在每个视图中都有一个<c:set var="someVar" value="#myBean.someVar" />
。我会尝试你的一些解决方案。
您可以使用<ui:param>
代替长EL 表达式的别名。
这个问题确实有点复杂。将部分状态保存方法设置为 false 对我有用。其他解决方案并不那么容易使用,因为不知道是这样,有很多地方我使用这种绑定。升级到最新的 JSF 版本并不能开箱即用。可能这将是未来的最佳解决方案。不过,非常感谢您的回答和解释!问题已回答。
我的解决方案是在视图范围的 bean 中只保留用户输入和操作侦听器(它们使用用户输入)。它通常是每页一个视图 bean。其他一切 - 组件绑定、可能的选项(用于组合框、列表等)我保留在请求范围的 bean 中。只有在必要时才使用会话处理 bean。我从不使用 JSTL——它在 JSF 中毫无意义。这就像在编译期间更改 JSF 代码一样。如果您使用 JSTL,那么恢复视图是没有意义的。遵守这些规则使我一切顺利。以上是关于即使已经实例化了 ManagedBean(例如在 AJAX 调用上),也会调用 @PostConstruct 方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章
发生验证错误后,如何使用 PrimeFaces AJAX 填充文本字段?