The inheritance relationship of Root/child webapplicationcontext in spring MVC
In the traditional spring MVC program there will be two WebApplicationContext , one is the parent, from the applicationContext.xml inside, one is the child, loaded from servlet-context.xml inside.
The two are inheritance relationships, and child webapplicationcontext is able getParent() to get to root webapplicationcontext through functions.
In short, the bean in child webapplicationcontext can be injected into the bean in root webapplicationcontext, and the parent Webapplicationcontext beans cannot be injected into the bean in child webapplicationcontext.
A typical content of Web. XML is:
<!--the definition of the Root Spring Container shared by all servlets and Filters- <context-param> <param-name>Contextconfiglocation</param-name> <param-value>Classpath*:/applicationcontext.xml</param-value> </context-param> <!--creates the Spring Container shared by all servlets and Filters-- <listener> <listener-class>Org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--Processes Application requests -- <servlet> <servlet-name>Appservlet</servlet-name> <servlet-class>Org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>Contextconfiglocation</param-name> <param-value>/web-inf/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>True</async-supported> </servlet> <servlet-mapping> <servlet-name>Appservlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
The root webapplicationcontext is initialized by listener, and the child webapplicationcontext is initialized through the servlet.
In this applicationContext.xml case, the component-scan is usually just a non-controller class, such as:
<context:component-scan base-package = "io.github.test" > <context:exclude-filter expression =" Org.springframework.stereotype.Controller " Span class= "Hljs-attribute" >type = "annotation" /> <context:exclude-filter type =< Span class= "Hljs-value" > "annotation" expression =" Org.springframework.web.bind.annotation.ControllerAdvice "/> </ context:component-scan ;
servlet-context.xmltypically only Component-scan controller classes, such as:
<context:component-scan base-package="Io.github.test.web" Use-default-filters="false"> <context:include-filter expression="Org.springframework.stereotype.Controller" Type="annotation" /> <context:include-filter type="annotation"expression=" Org.springframework.web.bind.annotation.ControllerAdvice " /> </context:component-scan>
If you do not component-scan the words separately, there may be problems with the bean's repeated initialization.
It was recommended by spring when it was officially started.
Root/child Webapplicationcontext the problem of inheritance
The bean in root webapplicationcontext can be shared among different child webapplicationcontext, and the bean area of the different child webapplicationcontext does not interfere. This would have been a very good design.
But there are actually a lot of problems:
* Many developers do not know that spring MVC has two webapplicationcontext. Causes a variety of repeatedly constructed beans, a variety of beans can not inject problems.
* There are beans, such as the global AOP processing class, assuming root webapplicationcontext is initialized, then the initialized bean in child webapplicationcontext is not processed.
Assuming that the class is initialized in child webapplicationcontext, there is no way to inject the classes in root webapplicationcontext.
* It is very troublesome to distinguish which beans are placed in root/child. Careless easy wrong, and mind.
A once and for all solution: beans are loaded by root Webapplicationcontext
When configuring metrics-spring at once. Configuring @EnableMetrics the configuration in which webapplicationcontext, I feel very sore.
Finally decided to try to move all the beans, including the controller, to the root webapplicationcontext. The inside applicationContext.xml is loaded, while the servlet-context.xml basic is empty. It turns out that program execution is completely fine.
Back on the Internet to search the next. Find some related discussions:
Http://forum.spring.io/forum/spring-projects/container/89149-servlet-context-vs-application-context
The approach of Spring boot
In spring boot, the Component-scan configuration is not required by default, so does it mean that there is only one webapplicationcontext in spring boot?
After the test, hair now spring boot in the default case is really just a webapplicationcontext: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext , so in spring boot in a lot of trouble.
Summarize
Spring's ApplicationContext inheritance mechanism is a very good design and can see similar ideas in so many other places. For example, Java's class loader. However, in most spring Web applications, it is enough to actually have just one webapplicationcontext. Assuming separate rott/child Webapplicationcontext can lead to confusion, and nothing.
It is recommended that all Service/controller be moved to root webapplicationcontext initialization.
On the inheritance relationship of Spring MVC's Webapplicationcontext