Jetty loads the spring-context container source code analysis, jettycontextpath
Start the order of web. xml with questions
Let's take the simplest spring mvc web. xml for example, what results will be produced if I put the order of the three in reverse or out of order?
Startup error? Or load unknown results? Is there no impact?
What is the result? Let's use practice to demonstrate the on-site demonstration of go-> jetty-spring-context project.
// Post the result after todo
How to configure applicationContext. xml and spring-mvc-servlet.xml
The simplest configuration (in this way, not only two containers are generated, but each container generates the same bean)
ApplicationContext:
Spring-mvc-servlet.xml
Correct Configuration
1 applicationContext. xml 2 <? Xml version = "1.0" encoding = "UTF-8"?> 3 <beans xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" 4 xmlns: context = "http://www.springframework.org/schema/context" 5 xmlns = "http://www.springframework.org/schema/beans" 6 xsi: schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context 7 http://www.springframework.org/schema/co Ntext/spring-context-4.1.xsd "> 8 <! -- Correct configuration --> 9 <context: component-scan base-package = "com. meituan. jetty. spring "> 10 <context: exclude-filter type =" annotation "expression =" org. springframework. stereotype. controller "/> 11 </context: component-scan> 12 </beans> 13 14 spring-mvc-servlet.xml15 <beans xmlns =" http://www.springframework.org/schema/beans "16 xmlns: xsi =" http://www.w3.org/2001/XMLSchema-instance "17 xmlns: context = "http://www.springfram Ework.org/schema/context "18 xsi: schemaLocation =" http://www.springframework.org/schema/beans19 http://www.springframework.org/schema/beans/spring-beans.xsd20 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> 21 <! -- Correct configuration --> 22 <context: component-scan base-package = "com. meituan. jetty. spring. controller "/> 23 <bean class =" org. springframework. web. servlet. view. internalResourceViewResolver "> 24 <property name =" prefix "value ="/"/> 25 <property name =" suffix "value = ". jsp "/> 26 </bean> 27 </beans>
Yes? Go-> the jetty-spring-context project demonstrated the problem. We found that there are indeed two containers, because the two containers can have the same beans at the same time, can the ApplicationContext container be removed directly?
How is the initialization order of applicationContext. xml and spring-mvc-servlet.xml?
Result: The initialization of applicationContext. xml takes precedence over the spring-mvc-servlet.xml.
What are the two context containers?
The following figure shows a few implementations of the applicationContext interface.
In-depth source code troubleshooting why no matter how you configure app. xml, it is always initialized before mvc
Let's use the source code to analyze the details step by step.
Start the jetty container Portal
................................ There is a large piece of code in front
Initialization calls the mms server's start method. In fact, the server does not have the start method, which is the start method of its parent class AbstractLifeCyle, and then calls back. Let's take a look at the structure of the server.
Before continuing to explain how the server is called Step by step, we need to know two things.
Essence of ContextLoaderListener and DispatcherServlet (insert)
ContextLoaderListerner implements an EventListenerEvent listener
Related Event Notifications are described in detail in my other wiki:
Deep source code for event notification mechanism # deep source code for event notification mechanism-ApplicationListener
You can also refer to the following link for details: Spring event notification mechanism.
ContextLoaderListerner's method contextInitialized will be called back |
DispatcherServlet is essentially a servlet. Of course, this is not to mention clearly.
The method of the DispatcherServlet parent class FrameworkServlet initServletBean will be called back |
At this time, we need to know one thing: contextLoaderListerner and DispatcherServlet are in two packages of spring. The former is in spring-web, and the latter is in spring-webmvc. This is helpful in understanding the latter.
Start the jetty container portal (continued)
Why does listener take precedence over servlet execution in any way?
To solve this problem, let's first look at the time when the listener is called back:
First, let's look at this figure. Here we have an image for WebAppContext and ContextHandler (of course, this is the jetty source code)
When jetty is started, a WebAppContext will be initialized (WebAppContext inherits ServletContextHandler, and ServletContextHandler inherits ContextHandler and they all implement it) object;
In the end, the startContext () method of the WebAppContext object will be implemented, such as the call chain:
What does the startContext method do? With questions, let's go to the following code:
We found that the ContextHandler contains a set of listener, and our ContextLoaderListener instance is also in this set;
We can see that the ContextLoaderListener and event Events are passed to the callContextInitialized method. Therefore, the contextInitialized method of the ContextLoaderListener will be called eventually,
So far, we have explained that ContextLoaderListener will be properly initialized;
For details about the ContextLoaderListener initialization process, refer to: How jetty initializes the spring container-ContextLoaderListener to initialize the context container Process
Why? Something seems wrong. Oh, yes. It is the startContext method of WebAppContext. How can I run the startContext method of ContextHandler,
Is the relationship of the Child class parent class;
Let's take a look at the call chain. Let's talk about why the start command of the server is called by the boot system in lifeCycle?
The original server inherits AbstractLifeCycle. jetty uses a lot of template methods and class template methods in the source code. We can also learn this design pattern during development to reduce repeated code and improve code reuse rate.
After talking about this, I haven't mentioned why listener is always executed before servlet?
Don't worry, and listen to the following explanation
As shown in the following figure, the WebAppContext doStart method is called. In this case, WebAppContext implements some of the functions, and the others directly call the doStart method of the parent class> ContextHandler.
(Handler, No. Isn't the parent class ServletContextHandler? Oh, ServletContextHandler hasn't rewritten this method)
Next, call the doStart method of ContextHandler.
ContextHandler calls the WebAppContext method of the subclass again startContext ()
WebAppContext first calls startWebApp, and then startWebApp calls the startContext method of the parent class ServletContextHandler again
This is interesting.: ServletContextHandler first calls the parent class, that is, the startContext method of ContextHandler. Do you still remember what happened to this method of the parent class?
Yes! The ContextLoadListener is initialized in the parent class, that is, all event notifications are initialized !!!
After the event notification is complete, call the servlet initialize method to initialize the servlet. servlet initialization details: Let's look at how jetty initializes the spring container-DispatcherServlet to initialize the context container.
That is to say, the callback of the frameworkServlet initialization method is caused by the startContext method of ServletContextHandler !!!
Check the execution sequence of listener and servlet:
So far, we have analyzed why the execution of listener before servlet initialization by jetty !!!
ContextLoaderListener initializes the ContextLoaderListener structure of the context container.
ContextLoaderListener entry
First, call back ContextLoaderListener's contextInitialized method.
Call the contextInitialized method of the parent class ContextLoader. At the first initialization, org. springframework. web. context. WebApplicationContext. ROOT = null
Then, create the context in step 1.
Let's see how context is created? What type is created? The red box determines the type of applicationContext to be created.
For example, use strategy to determine which type to create
How is strategy initialized?
Look
It is determined by this configuration file. The wepApplicationContext type is XmlWebApplicationContext, followed by configAndRefresh.
Finally, the refresh method of AbstractApplicationContext is called and initialization starts Based on the configuration file content;
Do you know the refresh initialization of AbstractApplicationContext? If you do not know, read this article about spring initialization sequence: Spring Init & Destroy # Main Entry of spring container.
DispatcherServlet initialization process of the context container DispatcherServlet Structure
DispatcherServlet entry
Initialize webApplicationContext,
Create webApplicationContext
The contextClass is determined in this way.
It is also instantiated by calling refresh.
Finally, the second container is initialized.