2.8 Continue to click the getTomcatWebServer method, find the initialize () method, and you can see the tomcat.start () method to start the Tomcat service.

0 35
Author: Li Yanke1 BackgroundSpringBoot is a framework, a new programming specifi...

Author: Li Yanke

1 Background

SpringBoot is a framework, a new programming specification. Its emergence simplifies the use of frameworks and also provides many convenient features, such as built-in tomcat, which is one of them. It allows us to avoid setting up the tomcat container, generating war files, deploying, and starting tomcat. Because of the built-in startup container, the application can be compiled directly into an executable jar package through the Maven command and started directly with the java -jar command, without the need to package it into a war file and then deploy it in Tomcat as before. So, how is the built-in tomcat implemented?

2 Tomcat startup process and principle

2.1 Download a springboot project

Download a project here https://start.spring.io/You can also create a new SpringBoot-Web project in idea.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Click on pom.xml to see the tomcat dependency

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>

2.2 Start from the entry point and explore step by step

Click into the run method

public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class<?>[] { primarySource }, args);
}

//Continue to click into the run method
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}

After entering this run method, you can see some initialization events that we are familiar with. The main process is also completed here.

2.3 The source code flow is roughly as follows

/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
/**1、Configure system properties*/
configureHeadlessProperty();
/**2. Get Listeners*/
SpringApplicationRunListeners listeners = getRunListeners(args);
/**Publish Application Starting Event*/
listeners.starting();
try {
/**3. Initialize Parameters*/
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
/**4. Configure Environment*/
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);

configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
/**5. Create Application Context*/
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
/**6. Prepare Context*/
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);

/**6. Refresh Context*/
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
/** 8. Publish the application started event */
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}

try {
/** 9. Publish the event that the application has been started */
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}

The code mainly uses a switch statement to create different ApplicationContexts based on the type of webApplicationType:

  • DEFAULT_SERVLET_WEB_CONTEXT_CLASS: Web type, instantiate AnnotationConfigServletWebServerApplicationContext
  • DEFAULT_REACTIVE_WEB_CONTEXT_CLASS: Reactive Web type, instantiate AnnotationConfigReactiveWebServerApplicationContext
  • DEFAULT_CONTEXT_CLASS: Non-Web type, instantiate AnnotationConfigApplicationContext

After creating the application context, let's take a look at the method for refreshing the context.

Step by step, click through breakpoints to enter the method and we see familiar code related to spring.

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//Prepare this context for refreshing.
//Before initialization, the main preparation work involves checking system properties and environment variables, such as setting and verifying environment variables required for Spring to start.
prepareRefresh();

// Instruct the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
// Prepare the bean factory by registering some classes
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
// Register bean factory post-processors and parse java code configuration for bean definitions
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
// Register bean post-processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
// Initialize the event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// To be implemented by subclasses, springBoot implements the creation of an embedded tomcat container here
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// It may not be necessary to have metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

2.5 The onRefresh() method calls the implementation of its subclass

That is, ServletWebServerApplicationContext

/** Get Servlet factory **/
this.webServer = factory.getWebServer(getSelfInitializer());

The createWebServer() method is used to start the web service, but Tomcat has not been started yet; it is only a WebServer created through ServletWebServerFactory. Let's continue to look at the ServletWebServerFactory:

this.webServer = factory.getWebServer(getSelfInitializer()); This method shows the implementation of TomcatServletWebServerFactory. Relevant Tomcat implementations.

2.6 getWebServer() method of TomcatServletWebServerFactory

Clearly see a new Tomcat being created.

2.7 After Tomcat is created, continue to analyze the related settings and parameters of Tomcat

@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {

/** 1. Create Tomcat instance **/
Tomcat tomcat = new Tomcat();
// Create Tomcat working directory
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);
/** 2. Set the connector for the created tomcat **/
tomcat.setConnector(connector);
/** 3. Set not to auto-deploy **/
tomcat.getHost().setAutoDeploy(false);
/** 4. Configure Tomcat container engine **/
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
/** Prepare Tomcat's StandardContext and add it to Tomcat **/
prepareContext(tomcat.getHost(), initializers);
/** Wrap the created Tomcat into a WebServer and return **/
return getTomcatWebServer(tomcat);
}

2.8 Continue to click the getTomcatWebServer method, find the initialize () method, and you can see the tomcat.start () method to start the Tomcat service.

//Start the server to trigger initialization listeners
//Start the Tomcat service
this.tomcat.start();
//Start blocking non-daemon processes
startDaemonAwaitThread();

//Tomcat.java

2.9 The console of TomcatWebServer.java will print this sentence

Tomcat started on port(s): 8080 (http) with context path ''

3 Summary

The startup of SpringBoot mainly starts through the instantiation of SpringApplication, and the startup process mainly does the following several things:

Configure system properties, obtain listeners, publish application startup events, initialize parameters, configure environments, create application contexts, preprocess contexts, refresh contexts, refresh contexts again, publish application startup events, and publish application startup completion events. Starting Tomcat is the step of refreshing the context.

When Spring Boot creates Tomcat, it first creates a context and passes the WebApplicationContext to Tomcat;

To start the Web container, it is necessary to call getWebserver () because the default Web environment is TomcatServletWebServerFactory, so the Tomcat's Webserver will be created, and the root context will be passed as a parameter to the getWebServer () of TomcatServletWebServerFactory; to start Tomcat, call the startup methods of Host and Engine in Tomcat.

3.1 Introduction to Tomcat-related names

你可能想看:
最后修改时间:
admin
上一篇 2025年03月25日 17:51
下一篇 2025年03月25日 18:14

评论已关闭