ApplicationContext ApplicationContext
After the environment is ready, print the Banner and then create the context. Because it is a Servlet environment, return AnnotationConfigServletWebServerApplicationContext here, it is the application context, One member variable is the beanFactory DefaultListableBeanFactory object references, it is the default of the IoC container.
SpringApplication->run(): prepareContext(context, environment, listeners, applicationArguments, printedBanner); PrepareContext (): // Execute initializers in applyInitializers(context) / / triggers the listener call application context initialization is completed (ApplicationContextInitializedEvent) event listeners. ContextPrepared (context); If (this.logStartupInfo) {logStartupInfo(context.getparent () == null); logStartupProfileInfo(context); }... // Add a load(context, sources.toarray (new Object[0])) to the BDN and BDM. // Listeners in SpringBoot are assigned to the application context to trigger listeners to call the ApplicationPreparedEvent event. ContextLoaded (context);Copy the code
Instantiation of Tomcat
AbstractApplicationContext - > refresh () : / / initialization in a container special bean onRefresh (); ServletWebServerApplicationContext - > onRefresh () : / / create a tomcat container createWebServer (); ServletWebServerApplicationContext->createWebServer(): ServletWebServerFactory factory = getWebServerFactory(); / / this is AnnotationConfigServletWebServerApplicationContext enclosing webServer = factory.getWebServer(getSelfInitializer()); initPropertySources();Copy the code
GetWebServerFactory inject ServletWebServerFactory subclass object (), introduced by ServletWebServerFactoryAutoConfiguration class, Finally instantiation TomcatServletWebServerFactory object, you can see the class in addition to Tomcat and Jetty and Undertow, are not added to the container, It’s the @conditionalonClass and @conditionalonmissingBean annotations that do the trick.
Here at last see the trail of the Tomcat / / TomcatServletWebServerFactory - > getWebServer () : / / object initialization Tomcat Tomcat Tomcat = new Tomcat (); // Set File baseDir = (this.basedirectory! = null) ? this.baseDirectory : createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); // Instantiate the connector component, internally instantiate Http11NioProtocol, Http11NioProtocol internal instantiation of Connector Connector = new Connector(this.protocol); // instantiate server and service components, then add service to server, service addConnector tomcat.getservice ().addconnector (connector); // A custom attribute value, such as the port number customizeConnector(connector); tomcat.setConnector(connector); // instantiate engine, service add engine, instantiate host, engine add host tomcat.gethost ().setautodeploy (false); . // Instantiate the context component, then instantiate the Wrapper component, then add the wrapper to the context, then add the context to host. Complete prepareContext(tomcat.gethost (), initializers); Return getTomcatWebServer(tomcat); // Start the Tomcat service.Copy the code
Properties starting with Server in the user profile are injected into the ServerProperties class member variable, which is used to customize Tomcat property values.
The structure of Tomcat is shown in the figure, where Server is a member variable attribute of the Tomcat class. Host, context, and Wrapper are the children member variables for each component.
Tomcat startup
Each component is a subclass of the abstract class ContainerBase, which in turn is a subclass of the abstract class LifecycleMBeanBase.
LifecycleBase->start(): If the lifecycle state is NEW, call init(), set the lifecycle state to STARTING_PREP, call the startInternal() method, LifecycleMBeanBase->initInternal(): Registers the current object with JMX ContainerBase->initInternal(): registers a startStop thread pool ContainerBase->startInternal(): puts the start of the child container into the startStop thread pool, waits for it to complete, and starts the background thread. LifecycleBase->fireLifecycleEvent(): Events that cause listeners to perform life-cycle state changes
Start server, Service, and Engine
The startup of Tomcat is mainly the startup of components, and the life cycle changes throughout it.
TomcatWebServer->initialize(): logger.info("Tomcat initialized with port(s): " + getPortsDescription(false)); . this.tomcat.start(); Tomcat->start(): server.start();Copy the code
The general process is shown in the figure below. Each component has an independent life cycle. Here component 2 is the last component of component 1, component 3 is the last component of component 2, and so on.
initInternal
In:
In initInternal() of the connector, the CoyoteAdapter is instantiated
startInternal
In:
Starting with engine, the child components are started as asynchronous threads.
The service calls mapperListener.start() to initialize the attributes of the route Mapper class.
Service Traverses the Connectors object to see that the connectors are already unbound.
Start host, context, and Wrapper
Because engines correspond to multiple hosts, and hosts to multiple contexts, their children are started as asynchronous threads.
ContainerBase->startInternal(): Container children[] = findChildren(); List<Future<Void>> results = new ArrayList<>(); for (int i = 0; i < children.length; i++) { results.add(startStopExecutor.submit(new StartChild(children[i]))); } // StartChild implements Callable interface StartChild ->call(): child.start();Copy the code
startInternal
In:
The context calls child.start(), and the wrapper start goes back to synchronization.
In startInternal() of the context, StandardManager is instantiated
The setManager(contextManager) of the context selects a sessionId generation method
Context onStartup(entry.getValue(),getServletContext()), iterating through its member variables initializers execute onStartup() // –1
Context calls super.threadStart() to start the background thread, which performs the backgroundProcess() method to determine whether the session has expired.
Context setState(lifecycleState.starting), unbind service and Connectors, click here for code and follow-up
Servlet, filter search and add
/ / - 1 end up in the following methods ServletWebServerApplicationContext - > selfInitialize () : // Scope new Application registerApplicationScope(servletContext); / / getServletContextInitializerBeans () returns the framework as well as custom servlet and filter subclass / / add the servlet context and the filter / / if the servlet, In children, still call the child. The start () to start the wrapper / / if it is a filter, in filterDefs and filterMaps embodies the for (ServletContextInitializer beans: getServletContextInitializerBeans()) { beans.onStartup(servletContext); } ServletWebServerApplicationContext->getServletContextInitializerBeans(): return new ServletContextInitializerBeans(getBeanFactory()); ServletContextInitializerBeans->ServletContextInitializerBeans(): this.initializerTypes = Collections.singletonList(ServletContextInitializer.class); / / found in the IoC container implementation ServletContextInitializer interface classes, they are of a generic category, one is the realization of the Servlet class, A class is the implementation of the Filter addServletContextInitializerBeans (the beanFactory); addAdaptableBeans(beanFactory); GetOrder () if it is a subclass of Ordered interface, or @order or @priority; Otherwise the default maximum integer List < ServletContextInitializer > sortedInitializers = this. Initializers. The values (). The stream () flatMap ((value) - > value.stream() .sorted(AnnotationAwareOrderComparator.INSTANCE)) .collect(Collectors.toList()); ServletContextInitializerBeans->addAdaptableBeans(): AddAsRegistrationBean (beanFactory, servlet.class, new ServletRegistrationBeanAdapter(multipartConfig)); / / add the IoC container of Filter interface in the class addAsRegistrationBean (the beanFactory, Filter class, new FilterRegistrationBeanAdapter ());Copy the code
So the context is done, so you go back and forth, and finally, Tomcat is done.
Since connector is not started, requests cannot be received at this time. Please refer to the timing and code of Tomcat receiving requestshere