I have a Spring-based web application, with two servlets - one for MVC and one for spring-ws. There are several beans used in the application, and they are autowired using annotations. Each time the application starts, it creates 3 instances of each bean type - even though they are singleton-scoped. The @PostConstruct methods are also called three times for each of them.
I understand that there are 3 application contexts = 1 common + 2 servlets, but each bean, controller, endpoint, etc. is created three times. At least the common beans, loaded in the parent application context should be instanced only once.
The base-package attribute of component-scan points to disjoint packages.
I've used a class to dump the context information (https://gist.github.com/1347171) and it appears there are three different contexts with identical structure (same beans). Their id's are "/project/", "/project/rest", "/project/soap".
I tried commenting out the ContextLoaderListener, removing the soap servlet and their associated XML files (applicationContext & soap-servlet) and moving the common stuff into the rest servlet (so that there is only one config xml and only one component-scan), and I still get 3 instances of each bean. In this case the application context id's are "/Project/" (exact casing), "/project/" and "/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>
applicationContext.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>
soap-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>