The introduction
In the past, I wrote several articles about SpringBoot, “Interview frequency question: SpringBoot automatic assembly principle you can say it”, “ny-level tutorial, hand to hand teach you to implement a SpringBoot starter”, these days suddenly a reader asked: can you say something about Spring’s father and son container? To be honest, this is actually a common problem in Spring Eight-part essay. In my impression, Spring is the parent container and SpringMvc is the child container. The child container can access the contents of the parent container, and the parent container cannot access the contents of the child container. A subclass can inherit common methods and variables from its parent class and access them, while the parent class cannot access methods and variables from its subclass. Here a few classic questions will be derived:
-
Why parent-child containers?
-
Can all classes be managed through the Spring container? (Configure global scanning in Spring’s ApplicationContext.xml)
-
Can we manage all the classes we need in a spring-MVC subcontainer (configuring global scanning in SpringMVC’s Spring-servlet.xml)?
-
Manage all classes in two containers at the same time? If the above four problems can be said to be an example, I think
Spring
Parent-child containers should not be a problem. We can take a look at the pictures of the father and son containers provided on the websiteTwo are shown aboveWebApplicationContext
Examples, for distinction, are called:Servlet WebApplicationContext
(sub-container),Root WebApplicationContext
Parent container. -
Servlet WebApplicationContext: This is the configuration of the Web layer in the J2EE three-tier architecture, such as controllers, view resolvers, and related beans. The configuration is loaded via the DispatchServlet provided in Spring MVC, usually with a configuration file named Spring-servlet.xml.
-
Root WebApplicationContext: This is to configure the Service layer and DAO layer in J2EE three-tier architecture, such as business beans, data sources, etc. Typically, the name of the configuration file is applicationContext.xml. In Web applications, it is loaded with ContextLoaderListener.
The start of the Spring
To understand the relationship, it is important to understand the Spring startup process. To figure out the startup process we need to build oneSpringMvc
Project, to be honest, used to itSpringBooot
Out of the box, suddenly turning around and building oneSpringMvc
The project was a bit strange, with a lot of configuration files. (Although you can also use annotations to do this.SpringMvc
We will not introduce the project, but when we set up the project, we can see that the console will output the following log:In the log, the time of each parent container and child container is printed.
How do I verify that there are two containers?
We just need toController
With ourService
In the implementationApplicationContextAware
Interface, you can know the corresponding management container: inService
We can see that the object that the parent container belongs to isXmlWebApplicationContext@3972
inController
The corresponding container object inXmlWebApplicationContext@4114
So these are two different containers.
Source code analysis
We know that SpringServletContainerInitializer from the servlet 3.0, Tomcat startup automatically load realized ServletContainerInitializer Interface class (need in meta-inf/services directory new configuration file), also known as SPI (Service Provider Interface) Mechanism, SPI application is quite wide, such as our JDBC, and Dubbo framework are useful, if there are not very familiar with SPI mechanism can go to learn. So our entrance is SpringServletContainerInitializer onStartup method, it should also be the web container to start the call Spring related to the first method.
Initialize SpringIoc
If we can’t find an entry point, we can take the log printed by the console and do a reverse lookup with the log. This should always find a place to start loading the parent container. On startup the console should print “Root WebApplicationContext: Initialization Started” and we’ll be able to locate the code with this log
`public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {` `if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) ! = null) {` `throw new IllegalStateException(` `"Cannot initialize context because there is already a root application context present - " +` `"check whether you have multiple ContextLoader* definitions in your web.xml!" ); ` `}` `servletContext.log("Initializing Spring root WebApplicationContext"); ` `Log logger = LogFactory.getLog(ContextLoader.class); ` `if (logger.isInfoEnabled()) {` `logger.info("Root WebApplicationContext: initialization started"); ` `}` `long startTime = System.currentTimeMillis(); ` `try {` `// Store context in local instance variable, To guarantee that ' '// it is available on ServletContext shutdown.' 'if (this.context == null) {'' // Create context by reflection `this.context = createWebApplicationContext(servletContext); ` `}` `if (this.context instanceof ConfigurableWebApplicationContext) {` `ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; ` `if (! cwac.isActive()) {` `// The context has not yet been refreshed -> provide services such as` `// setting the parent context, setting the application context id, etc` `if (cwac.getParent() == null) {` `// The context instance was injected without an explicit parent ->` `// determine parent for root web application context, if any.` `ApplicationContext parent = loadParentContext(servletContext); ` `cwac.setParent(parent); ` `} ` ` / / IOC container initialization ` ` configureAndRefreshWebApplicationContext (cwac, servletContext); ` `}` `}` `servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ` `ClassLoader ccl = Thread.currentThread().getContextClassLoader(); ` `if (ccl == ContextLoader.class.getClassLoader()) {` `currentContext = this.context; ` `}` `else if (ccl ! = null) {` `currentContextPerThread.put(ccl, this.context); ` `}` `if (logger.isInfoEnabled()) {` `long elapsedTime = System.currentTimeMillis() - startTime; ` `logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms"); ` `}` `return this.context; ` `}` `catch (RuntimeException | Error ex) {` `logger.error("Context initialization failed", ex); ` `servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); ` `throw ex; ` ` `} ` `}Copy the code
This code is where the parent container is created.
Initialize Spring MVC
Next, let’s look at where the child container is created: inFrameworkServlet
classDoes the above code have a question mark about how we are going to execute itFrameworkServlet
theinitServletBean
Methods. This is because we are inweb.xml
It’s configuredDispatcherServlet
And then the Web container will callDispatcherServlet
theinit
Method, and this method will only be executed once. Init method is going to do thatinitWebApplicationContext
This method is a startup execution sequence for the Web child container.
`<servlet>` `<servlet-name>dispatcher</servlet-name>` ` < servlet class - > org. Springframework. Web. Servlet. The DispatcherServlet < / servlet class - > ` ` / / if you don't configure the load - on startup - 1 The INTI method will no longer be executed on project startup. Instead, it is the first time to start <load-on-startup>1</load-on-startup> '</servlet>'Copy the code
The general process is as follows:From the above code we can see that the child container is re-reflected by itselfnew
Creates a new container as a child container and sets its parent toSpring
Initializing createdWebApplicationContext
. And then it’s all about loading our inweb.xml
Inwardly configuredSpringmvc
Configuration file, and then execute it through the created child containerrefresh
Method, this method I believe many people should be relatively clear.
Problem solving
Now that we know a startup process for the Sping parent and the SpingMvc child, and what each does, let’s go back to the four questions above.
-
Why does ** need parent-child containers? The primary purpose of the parent container should be to delimit framework boundaries. It smacks of a single duty. In the J2EE three-tier architecture, we generally use the Spring framework for management in the Service layer, while there are many choices in the Web layer, such as Spring MVC, Struts, etc. Therefore, we usually use separate configuration files for the Web layer. For example, in the case above, we initially used Spring-servlet.xml to configure the Web layer and applicationContext.xml to configure the Service and DAO layers. If we now wanted to replace the Web layer with Struts from Spring MVC, we would simply replace spring-servlet.xml with the Struts configuration file, and applicationContext.xml would not need to be changed.
-
Can all classes be managed through the Spring parent container? (Spring’s applicationContext.xml configates global scanning)** All classes are managed by the parent container as follows:
`<context:component-scan use-default-filters="false" base-package="cn.javajr">`
`<context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />`
`<context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />`
`<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />`
`<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />`
`</context:component-scan>`
Copy the code
Then, inSpringMvc
The scan packet path is not configured in the configuration of. It is obvious that this approach will not work, which will result in the interface being generated when we request it404
. Because in parsing the @reqestMapping annotationinitHandlerMethods
The delta function is just a pair ofSpring MVC
In a containerbean
Does not look up the parent containerbean
, so there is no need for the parent container to contain@RequestMapping
Annotated functions are processed and will not generate the correspondinghandler
. So when the request comes in there’s no one to process ithandler
, resulting in 404.
-
** Can we manage all the classes we need in a spring-MVC subcontainer (configuring global scanning in SpringMVC’s spring-servlet.xml)? ** This is the package scan configuration spring-servlet.xml this is possible. This works because it simply hands everything over to the child container, which executes refresh to load and manage everything in its configuration file. Although it can be done but generally should not be recommended to do so, generally people will not do so. If your project uses objects, or AOP, remember to put this part of the configuration file in the spring-MVC child container as well, otherwise part of the child container and part of the parent container may cause your objects or AOP to fail. Isn’t there a classic eight-part essay here? There are times when things don’t work, and this is one of them.)
-
** Manage all classes through two containers simultaneously? ** This question should be easier to answer, certainly not through this way, let alone will not cause other problems, first of all, two containers put a copy of the same object, resulting in memory waste. In addition, the child container overrides the parent container load. It is possible that the parent container is configured to generate proxy objects, but as soon as the quilt container overrides, it becomes a native object again. That’s why your stuff doesn’t work. A supplementary question: Is there a parent container in SpringBoot? See you next time!
conclusion
- In fact, the parent and child container for programmers is no sense, is a knowledge point is not what use, are
Spring
It helped us, but we still need to know that there is such a thing, otherwise we might not know how to start when we have a problem. Like why my thing doesn’t work, my thingaop
It’s not working. It’s all configured on the Internet.
The end of the
-
As a result of their talent and learning, it is inevitable that there will be mistakes, if you found the wrong place, but also hope that the message to me pointed out, I will correct it.
-
If you think the article is good, your forwarding, sharing, appreciation, like, message is the biggest encouragement to me.
-
Thank you for reading. Welcome and thank you for your attention.
-
Standing on the shoulders of giants pick apples: www.cnblogs.com/grasp/p/110…
javajr.cn
Phase to select
Recommend 👍 :CyclicBarrier of Java high concurrency programming foundation
Recommended 👍 : CountDownLatch for Java high concurrency programming foundation
Recommended 👍 : Semaphore for Java high concurrency programming foundation
Recommended 👍 : AQS for Java high Concurrency programming basics
Recommended 👍 : Abominable crawler directly put the production of 6 machines to climb hanging!