spring web, security + web.xml + mvc dispatcher + Bean is created twice
During the servlet container lifecycle, the container first initializes the ServletContextListener
, then the Filter
and Servlet
instances.
A Spring Web application typically loads two contexts: the root context and the dispatcher servlet context. The ContextLoaderListener
class is a ServletContextListener
which loads the application (or root) context. It identifies the file to load either through the context-param
with the name contextConfigLocation
as given in the web.xml like below
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml
</param-value>
</context-param>
or, by default, by looking for a file at /WEB-INF/applicationContext.xml
. Since you've specified /WEB-INF/mvc-dispatcher-servlet.xml
as the contextConfigLocation
, that context will be loaded.
Once this is done, the container initializes the DispatcherServlet
, which also loads a context. It identifies the file load either through an init-param
element with the name contextConfigLocation
as given in the web.xml below
<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/spring/appServlet/some-random-location.xml</param-value>
</init-param>
</servlet>
or, by default, by looking for a file at /WEB-INF/name-of-your-servlet-servlet.xml
. In other words, it takes the value of the <servlet-name>
element and appends -servlet.xml
to it and looks for it in WEB-INF
.
Since you haven't specified an init-param
with name contextConfigLocation
, the DispatcherServlet
loads the context file at /WEB-INF/mvc-dispatcher-servlet.xml
, since its name is mvc-dispatcher
. The context loaded by the DispatcherServlet
has access to the beans loaded by the ContextLoaderListener
, that's why we call that the root context (and the others children).
All this to say that both your ContextLoaderListener
and your DispatcherServlet
are creating their own copy of an ApplicationContext
by each loading a XmlWebApplicationContext
from the same file at /WEB-INF/mvc-dispatcher-servlet.xml
.
Identify what beans or configuration you think should be available to the whole application and put them in the file that will be loaded by the ContextLoaderListener
. Identify the beans or configuration you think should be available to the DispatcherServlet
and put them in its context file.
http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch16s02.html
The framework will, on initialization of a DispatcherServlet, look for a file named [servlet-name]-servlet.xml in the WEB-INF directory of your web application and create the beans defined there (overriding the definitions of any beans defined with the same name in the global scope).
So you can remove the context-param:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml
</param-value>
</context-param>