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

Java Spring应用程序初始化两次?,java,spring,spring-mvc,web-applications,initialization,Java,Spring,Spring Mvc,Web Applications,Initialization,当我开始运行我的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.j

当我开始运行我的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\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<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;
    }

}
<?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>
公共类ApplicationListenerBean实现ApplicationListener{
私有字符串消息;
ApplicationEvent(ContextRefreshedEvent事件)上的公共无效{
System.out.println(“--------------上下文刷新----------------”);
System.out.println(:::::::::::“+message+”:::::::::::::::::::”;
//其他的东西,比如记录器初始化、服务器初始化等等。。
}
公共字符串getMessage(){
返回消息;
}
公共无效设置消息(字符串消息){
this.message=消息;
}
}
我的applicationContext.xml如下所示:

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;
    }

}
<?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>

我的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>

SpringValidations
index.jsp
调度员
org.springframework.web.servlet.DispatcherServlet
上下文配置位置
/WEB-INF/dispatcher-servlet.xml
1.
调度员
*.html
上下文配置位置
/WEB-INF/applicationContext.xml
org.springframework.web.context.ContextLoaderListener
log4jConfigLocation
/WEB-INF/classes/log4j.xml
org.springframework.web.util.Log4jConfigListener
我的调度程序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>

/WEB-INF/messages/messages.properties
/WEB-INF/messages/mymessages.properties
我要知道,为什么上下文刷新的消息会出现两次

编辑:我知道有很多方法可以初始化spring应用程序。但是
初始化Spring应用程序(如记录器、域服务器启动以获得协议连接、声明线程等)的最佳和有效方法是什么


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

它会针对每个上下文、调度程序和应用程序进行刷新。尝试运行此测试:

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

您的
web.xml
中似乎声明了两个
?尝试移除其中一个

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

org.springframework.web.context.ContextLoaderListener

这似乎很正常,因为Spring MVC应用程序通常至少有两个上下文,请参见

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

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

  • servlet级别的spring上下文,其中包含与给定DispatcherServlet关联的所有bean

SpringMVC应用程序可以有多个Dispatcher,每个Dispatcher都有自己的上下文,并且都与通用应用程序范围的bean共享父上下文

在每个dispatcher上下文中,都有特定于dispatcher的bean,不能在其他上下文中注入,也不能在父上下文中注入,例如,所有用@Controller注释的bean

这确保了我们可以将公共上下文中定义的服务和DAOBean注入到任何控制器中,但我们永远不能将控制器注入到服务中,或将控制器/bean从一个调度器注入到另一个调度器中,从而保持调度器的隔离


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

我相信您误解了
ApplicationListener
。它用于侦听每个应用程序上下文事件,而不是web应用程序初始化/销毁事件。尝试改用
ServletContextListener

在web.xml中

<listener>
<listener-class>com.blablah.StartupListener</listener-class>
</listener>

这很正常。您有一个加载上下文的应用程序侦听器,还有一个在启动时加载并加载上下文的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>

SpringValidations
index.jsp
调度员
org.springframework.web.servlet.DispatcherServlet
上下文配置位置
/WEB-INF/dispatcher-servlet.xml
调度员
*.html
上下文配置位置
/WEB-INF/applicationContext.xml
org.springframework.web.context.ContextLoaderListener
log4jConfigLocation
/WEB-INF/classes/log4j.xml
org.springframework.web.util.Log4jConfigListener

您是否也有Spring MVC特定的上下文XML文件(例如webContext.XML)?发布您的
web.XML
dispatcher servlet.XML
(或任何调用该文件的文件)@请Keeling查看我的编辑。@sp00m请查看我的编辑。请查看class
org.springframework.context.SmartLifecycle
谢谢您的回复。如何一次完成?您在应用程序启动时尝试做什么?在我的一个应用程序中,我加载了一些在整个应用程序中共享的列表。刷新上下文时,我只需检查以确保列表已加载。有没有办法确定要执行的操作的状态,以便有条件地执行它们?但我们永远不能将控制器注入服务,也不能将控制器/bean从一个调度器注入另一个调度器,您能解释一下这是什么意思吗?如何访问dispatcher?