Spring应用程序上下文加载顺序

7
在我的web.xml文件中,我有一个“springmvc” servlet声明(它有对应的springmvc-servlet.xml文件)。
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/myapp/*</url-pattern>
</servlet-mapping>

我也有我的通常的applicationContext.xml文件。哪个会先加载?springmvc-servlet.xml还是applicationContext.xml?
我问这个问题的原因是,每当我在applicationContext.xml中放置元素时,我会收到一个严重的上下文错误。但是当我将该元素放在springmvc-servlet.xml中时,我的Web应用程序可以正常运行。
你有任何想法吗?
在另一个Web应用程序中,我在applicationContext.xml中使用并且它可以正常运行。
补充说明:我注意到aop:config的存在与mvc:annotation-driven相冲突。

请将异常堆栈跟踪复制到您的问题中。您是否在applicationContext.xml中定义了mvc命名空间的xsd? - MarrLiss
没有堆栈跟踪。我只从Tomcat得到了典型的严重上下文错误。 - chris
4个回答

5

applicationContext.xml 上下文是 dispatcher-servlet.xml 上下文的父级。我不知道这是否意味着它被首先加载,但在您的情况下这并不重要:

<mvc:annotation-driven /> 必须在 dispatcher-servlet.xml 中,因为它属于应用程序的 Web 部分。


根据观察,我不这么认为。我有一个 Web 应用程序,在 applicationContext.xml 中有 <mvc:annotation-driven />。事实上,如果我将其放在 xxxxx-servlet 中,我只会得到 SEVERE CONTEXT 错误。我需要该元素,因为我的控制器和服务使用注释 @Controller 和 @Service 进行标记。 - chris
@chris,能否分享一下服务器异常的具体信息和跟踪记录? - Bozho

3
我解决了我的问题!
事实证明,这与加载顺序或声明 <mvc:annotation-driven/> 的位置无关。
我尝试在另一个 Tomcat 上部署我的 Web 应用程序,惊讶地发现本地主机日志中有一个堆栈跟踪。通过反复试错,我有一个线索表明冲突与 <aop:config/> 有关。但是具体的冲突是什么?
然后我在日志文件中看到了这个错误:
java.lang.ClassCastException: org.aspectj.weaver.ResolvedType$Array cannot be cast to org.aspectj.weaver.ReferenceType

所以我们有一个强制类型转换异常。我在Google上搜索了上面的确切错误,并找到了这个链接:Spring 3: adding causes ClassCastException
看起来,主题发起人和我正面临着完全相同的问题。所以我下载了aspectj-1.6.10.jar,但我仍然缺少一个类。后来发现应该使用 aspectjweaver-1.6.9
我仍在使用一个非常旧的aspectjweaver。它的名称上没有任何版本号。问题解决了。案子结了。
顺便说一下,作为奖励,我手动展开了 <mvc:annotation-driven/> 元素到其等效的XML声明:
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="order" value="0" />
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator" ref="validator" />
        </bean>
    </property>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
        </list>
    </property>
</bean>

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />

根据我的研究,当您声明基于<mvc:annotation-driven/>时,它们完全相同。

感谢所有帮助过我的人。


1
除了web.xml之外,没有预定义的顺序。 发生如下情况:
  • Servlet引擎加载web.xml,触发所有定义的servlet、过滤器和监听器的加载
  • ContextLoaderListener加载根应用程序上下文XML,可能包括LocalSessionFactoryBean的bean定义,从而触发所有Hibernate映射XML文件的加载
  • DispatcherServlet加载Web应用程序上下文XML
通过研究web.xml来确定每种情况的顺序。
另请参阅: link

在我的web.xml中,我只有xxxxx-servlet.xml。我没有声明任何其他的Spring XML文件。applicationContext.xml会默认加载,无需特殊配置。我不太清楚为什么它可以根据应用程序的位置在某些应用程序上运行。 - chris
我正在消化这些信息并进行测试...我觉得我发现了一些东西。 - chris
好的,很高兴这些信息对你有帮助。 - Michel

0
您可能需要将mvc命名空间添加到应用程序上下文中:
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
>

(其他命名空间已剥离)


我已经有那些了。当我缺少这些模式时,Eclipse会自动抱怨。 - chris
是这样想的,但我只是为了完整性而检查一下。 - Sean Patrick Floyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接