我有一个基于 Spring 的 Web 应用程序,有两个 servlet——一个用于 MVC,一个用于 spring-ws。应用程序中使用了几个 bean,它们使用注释自动装配。每次应用程序启动时,它都会为每种 bean 类型创建 3 个实例——即使它们是单例范围的。@PostConstruct 方法也被调用了 3 次。
我知道有 3 个应用程序上下文 = 1 个通用 + 2 个 servlet,但是每个 bean、控制器、端点等都被创建了 3 次。至少在父应用程序上下文中加载的公共 bean 应该只实例化一次。
component-scan 的 base-package 属性指向不相交的包。
我使用了一个类来转储上下文信息(https://gist.github.com/1347171),并且似乎存在三个具有相同结构(相同 bean)的不同上下文。他们的 id 是“/project/”、“/project/rest”、“/project/soap”。
我尝试注释掉 ContextLoaderListener,删除soap servlet 及其关联的XML 文件(applicationContext 和soap-servlet)并将常见的东西移动到rest servlet(这样只有一个配置xml 和一个组件扫描),并且我仍然得到每个 bean 的 3 个实例。在这种情况下,应用程序上下文 ID 是“/Project/”(精确大小写)、“/project/”和“/project/”。
web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>soap</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>soap</servlet-name>
<url-pattern>/soap/*</url-pattern>
</servlet-mapping>
应用程序上下文.xml
<context:annotation-config/>
<context:component-scan base-package="test.common"/>
<task:annotation-driven/>
rest-servlet.xml
<mvc:annotation-driven/>
<context:component-scan base-package="test.rest"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="formHttpMessageConverter"/>
</util:list>
</property>
</bean>
<bean id="formHttpMessageConverter"
class="org.springframework.http.converter.FormHttpMessageConverter"/>
<mvc:interceptors>
<bean class="test.rest.Interceptor"/>
</mvc:interceptors>
肥皂-servlet.xml
<sws:annotation-driven/>
<context:component-scan base-package="test.soap"/>
<sws:dynamic-wsdl
id="service"
portTypeName="service"
locationUri="/soap/service"
targetNamespace="http://server/soap">
<sws:xsd location="/WEB-INF/SoapService.xsd"/>
</sws:dynamic-wsdl>
<sws:interceptors>
<bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="/WEB-INF/SoapService.xsd"/>
<property name="validateRequest" value="true"/>
<property name="validateResponse" value="true"/>
</bean>
</sws:interceptors>