Java Spring - 应用程序初始化两次?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20704086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring - application Initialized twice?
提问by Human Being
When I starts to run my spring application my tomcat , the ContextRefreshedEvent
fires twice. Please see the StackTrace.
当我开始运行我的 spring 应用程序我的 tomcat 时,会ContextRefreshedEvent
触发两次。请参阅堆栈跟踪。
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\Tools\Binn\;C:\Program Files\Microsoft SQL Server\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
My Initializer class will be as ,
我的 Initializer 类将是,
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
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;
}
}
And my applicationContext.xml will be as ,
而我的 applicationContext.xml 将是,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org./dtd/spring-beans.dtd">
<beans>
<bean id="test" class="com.pointel.applicationListener.ApplicationListenerBean">
<property name="message"
value="Now you can Start the Server Initialization !">
</property>
</bean>
</beans>
My web.xml will be ,
我的 web.xml 将是,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>SpringValidations</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
My dispatcher-servlet will be as,
我的调度程序 servlet 将是,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- Application Message Bundle -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- <property name="basename" value="/WEB-INF/messages/messages.properties" /> -->
<property name="basenames">
<list>
<value>/WEB-INF/messages/messages.properties</value>
<value>/WEB-INF/messages/mymessages.properties</value>
</list>
</property>
<property name="cacheSeconds" value="3000" />
</bean>
<!-- Scans the classpath of this application for @Components to deploy as beans -->
<context:component-scan base-package="com.pointel.controllers" />
<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />
<!-- <context:annotation-config /> -->
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views
directory -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Shall I know , Why the --------------- Context Refreshed -----------------message comes twice ?
我应该知道,为什么--------------- Context Refreshed -----------------消息出现两次?
Edit :I know there are many ways to initialize an spring application. But 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... ?
编辑:我知道有很多方法可以初始化 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... ?
Hope , you all can understand my question.
希望大家能理解我的问题。
采纳答案by Kevin Bowersox
Its getting refreshed for each context, Dispatcher and Application. Try running this test:
它为每个上下文、调度程序和应用程序刷新。尝试运行此测试:
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
System.out.println(context.getDisplayName());
}
回答by Will Keeling
You seem to have two <ContextLoaderListener>
s declared in your web.xml
? Try removing one of these.
你似乎<ContextLoaderListener>
在你的web.xml
? 尝试删除其中之一。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
回答by Angular University
This seems normal as Spring MVC application have usually at least two contexts, see this answer.
这似乎很正常,因为 Spring MVC 应用程序通常至少有两个上下文,请参阅此答案。
In this case this application has two different contexts that serve different purposes:
在这种情况下,这个应用程序有两个不同的上下文,用于不同的目的:
a global Spring context common to the whole application
a servlet-level spring context, which contains all the beans associated to a given dispatcher servlet.
整个应用程序通用的全局 Spring 上下文
servlet 级别的 spring 上下文,其中包含与给定调度程序 servlet 关联的所有 bean。
A Spring MVC application can have multiple dispatchers, each with it's own context and all sharing a parent context with common application-wide beans.
一个 Spring MVC 应用程序可以有多个调度程序,每个调度程序都有自己的上下文,并且都与通用的应用程序范围的 bean 共享一个父上下文。
In each dispatcher context there are beans specific of the dispatcher that cannot be injected in other contexts and neither on the parent context, for example all beans annotated with @Controller.
在每个调度程序上下文中,都有特定于调度程序的 bean,它们不能注入到其他上下文中,也不能注入到父上下文中,例如所有用 @Controller 注释的 bean。
This ensures that we can inject service and DAO beans defined in the common context in any controller, but we can never inject a controller into a service, or controllers/beans from one dispatcher into another dispatcher, keeping the dispatchers isolated.
这确保我们可以将定义在任何控制器的公共上下文中的服务和 DAO bean 注入,但我们永远不能将控制器注入服务,或者将控制器/bean 从一个调度程序注入另一个调度程序,从而使调度程序保持隔离。
According to the log, the first context initialised is the root context, and the second context is the dispatcher context, which is OK.
根据日志,初始化的第一个上下文是根上下文,第二个上下文是调度程序上下文,这是可以的。
回答by ramirezag
I believe you misunderstood ApplicationListener
. It is used to listen for each application context events not web app initialization/destruction events. Try using ServletContextListener
instead.
我相信你误会了ApplicationListener
。它用于侦听每个应用程序上下文事件,而不是 Web 应用程序初始化/销毁事件。尝试使用ServletContextListener
。
In web.xml
在 web.xml 中
<listener>
<listener-class>com.blablah.StartupListener</listener-class>
</listener>
StartupListener.java
启动监听器.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
}
回答by Houcem Berrayana
That's very normal. You have an application listener that loads a the context, and you have a servlet that loads on startup and loads the context also. Remove load on startup from the servlet declaration in web.xml. You web.xml will become tike this :
这是很正常的。您有一个加载上下文的应用程序侦听器,还有一个在启动时加载并同时加载上下文的 servlet。从 web.xml 中的 servlet 声明中删除启动时的负载。你的 web.xml 会变成这样:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>SpringValidations</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>