Spring – 应用程序初始化两次?

当我开始运行我的Spring应用程序我的tomcat时, ContextRefreshedEvent会触发两次。 请参阅StackTrace。

 Dec 20, 2013 6:07:56 PM org.apache.tomcat.util.digester.SetPropertiesRule begin WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:SpringValidations' did not find a matching property. Dec 20, 2013 6:07:56 PM org.apache.catalina.core.AprLifecycleListener init INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jre6\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Program Files/Java/jre6/bin/client;C:/Program Files/Java/jre6/bin;C:/Program Files/Java/jre6/lib/i386;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Microsoft SQL Server\80\Tools\Binn\;C:\Program Files\Microsoft SQL Server\90\Tools\binn\;F:\sub\svn\bin;%DERBY_HOME%\bin;D:\Lal\Lab\SW\apache-maven-3.0.4/bin;C:\Program Files\TortoiseSVN\bin;C:\Program Files\Java\jdk1.6.0_25\bin;;F:\Eclipse\sts-2.9.2.RELEASE; Dec 20, 2013 6:07:56 PM org.apache.coyote.http11.Http11Protocol init INFO: Initializing Coyote HTTP/1.1 on http-8080 Dec 20, 2013 6:07:56 PM org.apache.catalina.startup.Catalina load INFO: Initialization processed in 289 ms Dec 20, 2013 6:07:56 PM org.apache.catalina.core.StandardService start INFO: Starting service Catalina Dec 20, 2013 6:07:56 PM org.apache.catalina.core.StandardEngine start INFO: Starting Servlet Engine: Apache Tomcat/6.0.16 Dec 20, 2013 6:07:56 PM org.apache.catalina.loader.WebappClassLoader validateJarFile INFO: validateJarFile(F:\anand\Spring_Training\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\SpringValidations\WEB-INF\lib\servlet-api-2.5.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class Dec 20, 2013 6:07:56 PM org.apache.catalina.core.StandardContext addApplicationListener INFO: The listener "org.springframework.web.context.ContextLoaderListener" is already configured for this context. The duplicate definition has been ignored. Dec 20, 2013 6:07:56 PM org.apache.catalina.core.StandardContext addApplicationListener INFO: The listener "org.springframework.web.util.Log4jConfigListener" is already configured for this context. The duplicate definition has been ignored. Dec 20, 2013 6:07:56 PM org.apache.catalina.core.StandardContext addApplicationListener INFO: The listener "org.springframework.web.context.ContextLoaderListener" is already configured for this context. The duplicate definition has been ignored. Dec 20, 2013 6:07:56 PM org.apache.catalina.core.StandardContext addApplicationListener INFO: The listener "org.springframework.web.context.ContextLoaderListener" is already configured for this context. The duplicate definition has been ignored. log4j:WARN Continuable parsing error 108 and column 11 log4j:WARN The content of element type "logger" must match "(param*,level?,appender-ref*)". log4j:WARN Continuable parsing error 114 and column 11 log4j:WARN The content of element type "logger" must match "(param*,level?,appender-ref*)". Dec 20, 2013 6:07:57 PM org.apache.catalina.core.ApplicationContext log INFO: Initializing Spring root WebApplicationContext log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. --------------- Context Refreshed ----------------- :::::::::::::::::::::::: Now you can Start the Server Initialization ! ::::::::::::::::::::::::::::: Dec 20, 2013 6:07:57 PM org.apache.catalina.core.ApplicationContext log INFO: Set web app root system property: 'webapp.root' = [F:\anand\Spring_Training\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\SpringValidations\] Dec 20, 2013 6:07:57 PM org.apache.catalina.core.ApplicationContext log INFO: Initializing log4j from [F:\anand\Spring_Training\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\SpringValidations\WEB-INF\classes\log4j.xml] log4j:WARN Continuable parsing error 108 and column 11 log4j:WARN The content of element type "logger" must match "(param*,level?,appender-ref*)". log4j:WARN Continuable parsing error 114 and column 11 log4j:WARN The content of element type "logger" must match "(param*,level?,appender-ref*)". Dec 20, 2013 6:07:57 PM org.apache.catalina.core.ApplicationContext log INFO: Initializing Spring FrameworkServlet 'dispatcher' --------------- Context Refreshed ----------------- :::::::::::::::::::::::: Now you can Start the Server Initialization ! ::::::::::::::::::::::::::::: Dec 20, 2013 6:07:58 PM org.apache.coyote.http11.Http11Protocol start INFO: Starting Coyote HTTP/1.1 on http-8080 Dec 20, 2013 6:07:58 PM org.apache.jk.common.ChannelSocket init INFO: JK: ajp13 listening on /0.0.0.0:8009 Dec 20, 2013 6:07:58 PM org.apache.jk.server.JkMain start INFO: Jk running ID=0 time=0/16 config=null Dec 20, 2013 6:07:58 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 1659 ms 

我的初始化程序类将为,

 public class ApplicationListenerBean implements ApplicationListener { private String message; public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("--------------- Context Refreshed -----------------"); System.out.println( ":::::::::::::::::::::::: " +message+ " :::::::::::::::::::::::::::::"); // Other stuff like logger Initialization , Server Initailization etc.. } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } 

我的applicationContext.xml将是,

         

我的web.xml将是,

   SpringValidations  index.jsp   dispatcher org.springframework.web.servlet.DispatcherServlet  contextConfigLocation /WEB-INF/dispatcher-servlet.xml  1   dispatcher *.html   contextConfigLocation /WEB-INF/applicationContext.xml   org.springframework.web.context.ContextLoaderListener   log4jConfigLocation /WEB-INF/classes/log4j.xml   org.springframework.web.util.Log4jConfigListener   

我的调度程序 – servlet将是,

     <!--  -->   /WEB-INF/messages/messages.properties /WEB-INF/messages/mymessages.properties         <!--  -->       

我知道吗,为什么—————上下文刷新—————–消息来了两次?

编辑:我知道有很多方法可以初始化spring应用程序。 但是what is the best and the efficient way to initialize an Spring application like logger,Domain server startup to get protocol connection , stating the threads etc... ?

希望,你们都能理解我的问题。

它会针对每个上下文,Dispatcher和Application进行刷新。 尝试运行此测试:

  public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext context = event.getApplicationContext(); System.out.println(context.getDisplayName()); } 

这看起来很正常,因为Spring MVC应用程序通常至少有两个上下文,请参阅此答案 。

在这种情况下,此应用程序有两个不同的上下文,用于不同的目的:

  • 整个应用程序共有的全局Spring上下文

  • 一个servlet级的spring上下文,它包含与给定的dispatcher servlet关联的所有bean。

Spring MVC应用程序可以有多个调度程序,每个调度程序都有自己的上下文,并且所有调度程序都与常见的应用程序范围的bean共享父上下文。

在每个调度程序上下文中,都有特定于调度程序的bean,这些bean不能在其他上下文中注入,也不能在父上下文中注入,例如所有使用@Controller注释的bean。

这确保了我们可以在任何控制器中注入在公共上下文中定义的服务和DAO bean,但是我们永远不能将控制器注入服务,或者将控制器/ bean从一个调度程序注入另一个调度程序,从而使调度程序保持隔离状态。

根据日志,初始化的第一个上下文是根上下文,第二个上下文是调度程序上下文,这是正常的。

这很正常。 您有一个加载上下文的应用程序侦听器,并且您有一个在启动时加载并加载上下文的servlet。 从web.xml中的servlet声明中删除启动时的负载。 你的web.xml将成为这样的:

   SpringValidations  index.jsp   dispatcher org.springframework.web.servlet.DispatcherServlet  contextConfigLocation /WEB-INF/dispatcher-servlet.xml    dispatcher *.html   contextConfigLocation /WEB-INF/applicationContext.xml   org.springframework.web.context.ContextLoaderListener   log4jConfigLocation /WEB-INF/classes/log4j.xml   org.springframework.web.util.Log4jConfigListener   

您似乎在web.xml声明了两个 ? 尝试删除其中一个。

  org.springframework.web.context.ContextLoaderListener  

我相信你误解了ApplicationListener 。 它用于监听每个应用程序上下文事件而不是Web应用程序初始化/销毁事件。 请尝试使用ServletContextListener

在web.xml中

  com.blablah.StartupListener  

StartupListener.java

 public class StartupListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent event) { System.out.println("--------------- Context Initialized -----------------"); // If want to get a bean ServletContext context = event.getServletContext(); ApplicationContext ctx = (ApplicationContext) WebApplicationContextUtils.getRequiredWebApplicationContext(context); MyBean bean = (MyBean) ctx.getBean("myBean"); } // Omitted for brevity }