@PostConstruct方法为同一请求调用两次

我正在使用JSF 2.0和GlassFish 3.0。

我有以下Managed Bean:

@ManagedBean @RequestScoped public class OverviewController{ private List eventList; @PostConstruct public void init(){ System.out.println("=> OverviewController - init() - enter"); System.out.println("=< OverviewController - init() - exit"); } } 

overview.xhtml文件中,我从OverviewController中调用了不同的属性或方法。

  ...  

一切正常,但问题出在日志文件中:

 INFO: Enter : RESTORE_VIEW 1 INFO: Exit : RESTORE_VIEW 1 INFO: Enter : RENDER_RESPONSE 6 INFO: => OverviewController - init() - enter INFO: => Overview Controller - updateSelectedTab() - enter INFO: =< Overview Controller - updateSelectedTab() - exit INFO: = OverviewController - init() - enter INFO: => Overview Controller - updateSelectedTab() - enter INFO: =< Overview Controller - updateSelectedTab() - exit INFO: =< OverviewController - init() - exit INFO: Exit : RENDER_RESPONSE 6 

正如您所看到的,init()方法在同一个请求中被调用两次,没有任何理由。 据我所知,每个请求都会调用一次使用PostConstruct注释的方法。 我错了吗?

编辑:页面上没有使用AJAX。 我用firebug检查了请求的数量。 有树请求:

  • 1.一个用于javax.faces.resource (GET)
  • 2.一个用于css文件(GET)
  • 3.One for overview.xhtml (GET)

如果您有多个框架管理同一个bean类,就会发生这种情况。 例如JSF CDI,或JSF Spring,或CDI Spring等。仔细检查bean上的配置和注释。

如果您正在使用CDI并且在整个class级中使用多个@Named注释,也会发生这种情况。 例如,@ @Named在类上直接将其注册为托管bean,另一个在@Produces getter方法上注册。 你需要问问自己这是否真的有必要。 您也可以使用#{bean.someObject}而不是#{someObject}

 @Named @RequestScoped public class Bean { @PostConstruct public void init() { // ... } @Named @Produces public SomeObject getSomeObject() { // ... } } 

如果您的托管bean扩展了一些抽象类,而该方法又是@PostConstruct ,那么也会发生这种情况。 您应该从中删除注释。 或者,您应该使init方法成为抽象,而不是在实现bean上使用@PostConstruct

 public abstract class BaseBean { @PostConstruct public void postConstruct() { init(); } public abstract void init(); } 

init()方法和@PostConstruct方法都可能触发并导致此行为。 尝试更改init()方法的名称和/或将其设置为private 。 我认为这可能与您的问题有关:

http://javahowto.blogspot.com/2011/07/servlet-init-method-vs-postconstruct.html

我还在这里找到了关于调试JSF生命周期的好文章: 调试JSF生命周期