SpringBoot boot source code parsing – AutoConfigure implementation principle SpringBoot source code parsing – @aliasfor annotation annotation SpringBoot source code parsing – SpringBoot boot boot boot process @ComponentScan implementation principle SpringBoot source parsing – @value, @autoWired implementation principle SpringBoot source parsing – Tomcat, SpringMVC starts SpringBoot source parsing — Logging, Environment starts

In this article, by reading the source code of SpringBoot, share the startup process of Tomcat and SpringMvc components in SpringBoot. Source code analysis based on Spring Boot 2.1

Tomcat

In analytical SpringBoot the article said that the SERVLET applications use ApplicationContext AnnotationConfigServletWebServerApplicationContext. The parent class ServletWebServerApplicationContext, create and initialize through ServletWebServerFactory WebServer, WebServer compatible with different servlet container (tomcat, jetty, Netty, which provides uniform start and stop operations. ServletWebServerApplicationContext is also responsible for the registration Servlet Filter, ServletContextListener work. ServletWebServerApplicationContext# servletConfig, GenericWebApplicationContext# servletContext is the servlet specification class provides.

ApplicationContext#run -> AnnotationConfigServletWebServerApplicationContext#refresh -> AbstractApplicationContext#refresh -> AbstractApplicationContext#onRefresh -> ServletWebServerApplicationContext#onRefresh -> ServletWebServerApplicationContext#createWebServer

private void createWebServer() {
	WebServer webServer = this.webServer;
	ServletContext servletContext = getServletContext();
	if (webServer == null && servletContext == null) {
		ServletWebServerFactory factory = getWebServerFactory();
		// # 1
		this.webServer = factory.getWebServer(getSelfInitializer());	
	}
	else if(servletContext ! = null) { try { //# 2
			getSelfInitializer().onStartup(servletContext);		
		}
		catch (ServletException ex) {
			throw new ApplicationContextException("Cannot initialize servlet context", ex);
		}
	}
	initPropertySources();
}
Copy the code

Create webServer # 1, note getSelfInitializer () through reference method constructs a ServletContextInitializer, The ServletContextInitializer invokes ServletWebServerApplicationContext# selfInitialize method # 2 webServer already exists. Direct call ServletWebServerApplicationContext# selfInitialize

ServletWebServerFactoryConfiguration to judge the current servlet container that exist in the JAVA environment, constructs the corresponding WebServerFactory. I will focus only on Tomcat here. TomcatServletWebServerFactory#getWebServer

public WebServer getWebServer(ServletContextInitializer... initializers) {
	// # 1Tomcat tomcat = new Tomcat(); File baseDir = (this.baseDirectory ! = null) ? this.baseDirectory : createTempDir("tomcat");
	tomcat.setBaseDir(baseDir.getAbsolutePath());	
	Connector connector = new Connector(this.protocol);
	tomcat.getService().addConnector(connector);
	customizeConnector(connector);
	tomcat.setConnector(connector);
	tomcat.getHost().setAutoDeploy(false);
	configureEngine(tomcat.getEngine());
	for(Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } / /# 2
	prepareContext(tomcat.getHost(), initializers);	
	// # 3
	return getTomcatWebServer(tomcat);	
}
Copy the code

#1 Construct the Tomcat object and configure the related properties #2 make a pre-configured Tomcat Context #3 convert to Spring’s TomcatWebServer object

Step # 2 will construct a TomcatStarter, TomcatStarter is a ServletContainerInitializer implementation class. ServletContainerInitializer also is provides the servlet specification, after the servlet container invoked ServletContainerInitializer# onStartup.

TomcatStarter# initializers are ServletContextInitializer array, TomcatStarter# onStartup will traverse the array, Call ServletContextInitializer# onStartup. ServletWebServerApplicationContext# getSelfInitializer createWebServer method # 1 procedure call () method to construct a ServletContextInitializer, The ServletContextInitializer has been passed to TomcatServletWebServerFactory# getWebServer and used to construct the TomcatStarter. So after the tomcat startup will eventually call ServletWebServerApplicationContext# selfInitialize

private void selfInitialize(ServletContext servletContext) throws ServletException {
	// # 1
	prepareWebApplicationContext(servletContext);	
	registerApplicationScope(servletContext);	
	WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
	// # 2
	for(ServletContextInitializer beans : getServletContextInitializerBeans()) { beans.onStartup(servletContext); }}Copy the code

#1 Get the relevant properties from the ServletContext and set them in the SpringContext. # 2 find a Spring in the context of ServletContextInitializer, and call the onStartup method. ServletContextInitializer is a configuration interface, programmatically configure the Servlet 3.0 + ServletContext. Its implementation class FilterRegistrationBean ServletRegistrationBean, ServletListenerRegistrationBean can be added a Filter to the ServletContext, Servlet, ServletContextListener.

TomcatWebServer# constructor -> TomcatWebServer#initialize

private void initialize() throws WebServerException {
	// # 1
	logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));	
	synchronized (this.monitor) {
		try {
			addInstanceIdToEngineName();
			// # 2
			Context context = findContext();	
			context.addLifecycleListener((event) -> {
				if(context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) { removeServiceConnectors(); }}); //# 3
			this.tomcat.start();	

			rethrowDeferredStartupExceptions();

			// # 4
			try {
				ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());	
			}
			catch (NamingException ex) {
				// Naming is not enabled. Continue
			}

			// # 5
			startDaemonAwaitThread();	
		}
		catch (Exception ex) {
			stopSilently();
			destroySilently();
			throw new WebServerException("Unable to start embedded Tomcat", ex); }}}Copy the code

#1 Print the Tomcat startup log #2 Obtain the Tomcat Context and configure related attributes #3 Start Tomcat, And call ServletContainerInitializer# onStartup bind this # 4 # 5 because all tomcat thread is a background thread, so you want to create a blocking the background thread process.

SpringMVC

Starting the SpringMVC component is relatively simple.

RequestMappingHandlerAdapter WebMvcAutoConfiguration responsible for construction, HandlerMethodReturnValueHandler HttpMessageConverter, RequestMappingHandlerMapping about for SpringMVC DispatcherServlet DispatcherServletAutoConfiguration component is responsible for the structure components, such as, can refer to previous articles Spring Mvc principles

Used in DispatcherServletAutoConfiguration DispatcherServletRegistrationBean DispatcherServlet to registration to the ServletContext, DispatcherServletRegistrationBean inherited ServletRegistrationBean, finally by ServletWebServerApplicationContext# selfInitialize complete injection operation.

@webFilter, @WebListener, @webServlet can also inject Servlet, Filter, ServletContextListener. (the three interfaces are the servlet specification) these annotations by @ ServletComponentScan annotation processing, @ ServletComponentScan annotations by introducing ServletComponentScanRegistrar @ Import, ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar (about ImportBeanDefinitionRegistrar interface, You can review the previous article parsing SpringBoot AutoConfigure), ServletComponentScanRegistrar# registerBeanDefinitions ServletComponentRegisteringPostProcessor is introduced, The PostProcessor scans @webFilter, @WebListener, and @WebServlet annotations in the corresponding directory and processes them using the corresponding ServletComponentHandler. You can read the code for yourself if you are interested.

If you think this article is good, welcome to pay attention to my wechat public number, your attention is my motivation!