With the rise of microservices, the SpringBoot framework is becoming more and more popular. I believe that most companies have already started to use this framework, and we will use this framework when developing our test platform. But the principle of this framework do not know whether you understand, the last article said that it is used, so this time to talk about the startup principle of SpringBoot, every startup we will use this startup class.

@SpringBootApplication
public class SpringbootApplication {
    public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class,args); }}Copy the code

As you can see from the code, the two important points are the @SpringBootApplication annotation and the springApplication.run annotation.

First, look at the @SpringBootApplication annotation

It is the core annotation of SpringBoot, and it is also a composite annotation. Let’s click on this annotation to have a look:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} )
public @interface SpringBootApplication {
.....
}
Copy the code

There are three important annotations, which are @SpringBootConfiguration, @EnableAutoConfiguration, and @ComponentScan. And then I’m going to click on @springBootConfiguration,

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
Copy the code

You can see that there is an @Configuration annotation in there, and those of you who know Spring should know what this annotation does. Therefore, from the above analysis, in fact, the core annotation @SpringBootApplication contains three important annotations, namely @Configuration, @EnableAutoConfiguration and @ComponentScan. So let’s go back to the source code and explain in detail what these three annotations do.

This is the @Configuration annotation used by the Javaconfig-based SpringIoc container Configuration class. SpringBoot recommends using the Javaconfig-based Configuration. If you use the @Configuration annotation, the delegate is itself an Ioc Configuration class. A quick note on how it differs from XML configuration.

A, the difference of expression

When we write XML, we write it like this

<? xml version="1.0" encoding="UTF-8"? > <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
        default-lazy-init="true"> <! -- Bean definition --> </beans>Copy the code

If we use JavaConfig configuration to write this

@Configuration
public class SpringConfiguration{
      / / bean definition
}
Copy the code

B. Register bean definition layer

Using XML

<bean id="mailService" class=".. MailServiceImpl">... </bean>Copy the code

If we use JavaConfig configuration to write this

@Configuration
 public class MailConfiguration{
     @Bean
     public MailService mailService(a){
         return newMailServiceImpl(); }}Copy the code

The return value of any method labeled @bean is registered with Spring’s IoC container as a Bean definition, and the method name defaults to the id of the Bean definition. This is how XML is written when beans depend on each other

<bean id="mailService" class=".. MailServiceImpl">
     <propery name ="dependencyService" ref="dependencyService" />
 </bean>
 <bean id="dependencyService" class="DependencyServiceImpl"></bean>
Copy the code

If we use JavaConfig configuration to write this

 @Configuration
 public class MailConfiguration{
      @Bean
      public MailService mailService(a){
          return new MailServiceImpl(dependencyService());
      }
     
      @Bean
      public DependencyService dependencyService(a){
         return newDependencyServiceImpl(); }}Copy the code

If the definition of a bean depends on another bean, you can simply call the dependent bean creation method in the corresponding JavaConfig class. The @Configuration annotation indicates that this class can use the Spring IoC container as the source for the bean definition.

The @Bean annotation tells Spring that an annotation method with an @bean will return an object that should be registered as a Bean in the Spring application context. That’s a brief explanation of the @Configuration annotation.

2, @ ComponentScan, next we said this important note, it is the main function of the automatic scan and load qualified components (such as @ Component and @ Repository, etc.) or bean definition, finally put the bean definition is loaded into the Ioc container. So it is best to place the SpringBoot boot class under the root package, since basePackages are not specified by default.

The @enableAutoConfiguration annotation is also the most important of the three. It allows Spring to automatically configure the @enableAutoConfiguration annotation with the help of @import. Load all bean definitions that qualify for automatic configuration into the IoC container.

In the same way that @enablembeanexport is used to load jMX-related bean definitions into the IoC container via @import. @enableAutoConfiguration will automatically configure the project based on jar dependencies in the classpath. For example, if we add a spring-boot-starter-Web dependency, Tomcat and SpringMVC dependencies will be automatically added. And SpringBoot automatically configures Tomcat and SpringMVC. So let’s go in and look at this annotation.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<? >[] exclude()default {};

    String[] excludeName() default {};
}
Copy the code

It is important to have two annotations, one is @ AutoConfigurationPackage, @ Import ({EnableAutoConfigurationImportSelector. Class}), This annotation loads the beans that meet the auto-configuration criteria into the SpringIoc container.

Our point in this EnableAutoConfigurationImportSelector. Class in this class, you can see it inherited AutoConfigurationImportSelector this class.

@Deprecated
public class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
    public EnableAutoConfigurationImportSelector(a) {}protected boolean isEnabled(AnnotationMetadata metadata) {
        return this.getClass().equals(EnableAutoConfigurationImportSelector.class)? ((Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, Boolean.valueOf(true))).booleanValue():true; }}Copy the code

We then enter AutoConfigurationImportSelector look at in this class.

public class AutoConfigurationImportSelector implements DeferredImportSelector.BeanClassLoaderAware.ResourceLoaderAware.BeanFactoryAware.EnvironmentAware.Ordered {...protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
               List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
               Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
               returnconfigurations; }...Copy the code

This class has a getCandidateConfigurations () method, its role is to introduce the system has good class loading, we can see that there is a SpringFactoriesLoader. LoadFactoryNames () this method, continue to point in check. The SpringFactoriesLoader, whose main function is to load the configuration from the specified configuration file meta-INF/Spring.Factories

   public static List<String> loadFactoryNames(Class
        factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();

        try{ Enumeration ex = classLoader ! =null? classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");
            ArrayList result = new ArrayList();

            while(ex.hasMoreElements()) {
                URL url = (URL)ex.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }

            return result;
        } catch (IOException var8) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8); }}Copy the code

The “meta-INF /spring.factories” configuration file is read if the classLoader is not null. Spring. Factories in this package.

Then we click on the profile.

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider

Copy the code

From this we can see that it helps us configure the full path of many classes, such as if you want to integrate Freemarker, Redis, etc. According to the full name of the class of the @ EnableAutoConfiguration org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration as a lookup Key, The value of value is a set of @Configuration classes.

So, @enableAutoConfiguration automatically searches for all meta-INF/Spring. factories configuration files from your classpath, And will the org. Springframework. Boot. Autoconfigure. EnableutoConfiguration corresponding configuration items through reflection (Java Refletion) instantiated into the corresponding Ioc container Configuration class in JavaConfig form labeled @Configuration, then aggregated into one and loaded into the Ioc container.

So that’s the analysis of the three annotations in the @SpringBootApplication annotation, just to sum up what the @SpringBootApplication annotation does is to get a lot of things ready, depending on our application or our configuration, what’s used, so let’s move on, Its run method.

Springapplication.run () startup process source code analysis

If there’s any auto-configuration that’s used to execute the run method, like the built-in Tomcat, let’s look for the built-in Tomcat, click on the run() method, and there’s a run method in there

 public static ConfigurableApplicationContext run(Object source, String... args) {
        return run(new Object[]{source}, args);
    }

Copy the code

We continue to click on the run() method and write an explanation of the source code in the comments on each line for your convenience.

 public ConfigurableApplicationContext run(String... args) {
        // Create and start the timing monitor class
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        // Initializes the application context and exception report collection
        ConfigurableApplicationContext context = null;
        Object analyzers = null;
        // Set the system property 'java.awt.headless'
        this.configureHeadlessProperty();
        
        // Create all Spring run listeners and publish application start events
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        try {
            // Initialize the default application parameter class
            DefaultApplicationArguments ex = new DefaultApplicationArguments(args);
            // Prepare the Spring environment based on run listeners and application parameters
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, ex);
            
            // Create the Banner print class
            Banner printedBanner = this.printBanner(environment);
            
            // Create the application context
            context = this.createApplicationContext();
            new FailureAnalyzers(context); 
             
            // Prepare the application context
            this.prepareContext(context, environment, listeners, ex, printedBanner);
            
           // Refresh the application context
            this.refreshContext(context);
             
            // Apply context refresh post-processing
            this.afterRefresh(context, ex);
            listeners.finished(context, (Throwable)null);
            // Stop the timer monitoring class
            stopWatch.stop();
            // Logs are generated to record the name and time of the execution main class
            if(this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            // Returns the application context
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
            throw newIllegalStateException(var9); }}Copy the code

So we’re looking at refreshContext(context); Refresh the context, let’s click on it

 private void refreshContext(ConfigurableApplicationContext context) {
        this.refresh(context);
        if(this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            } catch(AccessControlException var3) { ; }}}Copy the code

Click on the refresh(Context) method

protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
        ((AbstractApplicationContext)applicationContext).refresh();
    }
Copy the code

It calls (AbstractApplicationContext applicationContext). The refresh (), click on the refresh () method

public void refresh(a) throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if(this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches(); }}}Copy the code

This is the loading process of a Spring bean. This is the loading process of a Spring bean. The main thing that’s going on here is this method onRefresh(),

protected void onRefresh(a) throws BeansException {}Copy the code

It doesn’t implement, so let’s see what it does implement,

How we see the tomcat is embedded, is because see tomcat so definitely ServletWebServerApplicationContext this class.

   protected void onRefresh(a) {
        super.onRefresh();

        try {
            this.createWebServer();
        } catch (Throwable var2) {
            throw new ApplicationContextException("Unable to start web server", var2); }}Copy the code

So there’s a createWebServer() method in here, which creates a Web container, so let’s go in and see,webServer is created with a ServletWebServerFactory, so let’s take a look at this class.

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

Enter the ServletWebServerFactory interface class and guess that it should be able to create several different types of containers. Let’s click on its implementation class

@FunctionalInterface
public interface ServletWebServerFactory {
    WebServer getWebServer(ServletContextInitializer... var1);
}
Copy the code

So we can see that the interface implementation class includes TomcatServletWebServerFactory and JettyServletWebServerFactory, because want to see the tomcat, So we order into TomcatServletWebServerFactory look at:

 public WebServer getWebServer(ServletContextInitializer... initializers) {
        Tomcat tomcat = new Tomcat();
        File baseDir = this.baseDirectory ! =null?this.baseDirectory:this.createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        // Create the Connector object
        Connector connector = new Connector(this.protocol);
        tomcat.getService().addConnector(connector);
        this.customizeConnector(connector);
        tomcat.setConnector(connector);
        tomcat.getHost().setAutoDeploy(false);
        this.configureEngine(tomcat.getEngine());
        Iterator var5 = this.additionalTomcatConnectors.iterator();

        while(var5.hasNext()) {
            Connector additionalConnector = (Connector)var5.next();
            tomcat.getService().addConnector(additionalConnector);
        }

        this.prepareContext(tomcat.getHost(), initializers);
        return this.getTomcatWebServer(tomcat);
    }
Copy the code

This method creates a Tomcat object, puts all the connections into Tomcat, and returns the getTomcatWebServer() method. Let’s take a look at what’s in this method and continue into the getTomcatWebServer() method.

protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
        return new TomcatWebServer(tomcat, this.getPort() >= 0);
    }
Copy the code

Enter the TomcatWebServer() method

    public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
        this.monitor = new Object();
        this.serviceConnectors = new HashMap();
        Assert.notNull(tomcat, "Tomcat Server must not be null");
        this.tomcat = tomcat;
        this.autoStart = autoStart;
        this.initialize();
    }
Copy the code

The main one is initialize(), so let’s click on it

 private void initialize(a) throws WebServerException {
// You will see this log on the console
logger.info("Tomcat initialized with port(s): " + this.getPortsDescription(false));
        Object var1 = this.monitor;
        synchronized(this.monitor) {
            try {
                this.addInstanceIdToEngineName();
                Context ex = this.findContext();
                ex.addLifecycleListener((event) -> {
                    if(ex.equals(event.getSource()) && "start".equals(event.getType())) {
                        this.removeServiceConnectors(); }});// Start the Tomcat service
                this.tomcat.start();
                this.rethrowDeferredStartupExceptions();

                try {
                    ContextBindings.bindClassLoader(ex, ex.getNamingToken(), this.getClass().getClassLoader());
                } catch (NamingException var5) {
                    ;
                }

                this.startDaemonAwaitThread();
            } catch (Exception var6) {
                this.stopSilently();
                throw new WebServerException("Unable to start embedded Tomcat", var6); }}}Copy the code

Let’s go to the start() method

 public void start(a) throws LifecycleException {
        this.getServer();
        this.server.start();
    }
Copy the code

A Tomcat server contains only one server. A Server can contain multiple services. A service has only one Container and multiple connectors. Multiple connectors and a Container form a Service,

That’s how we started Tomcat from springApplication.run () step by step with the source code. The process may be a bit long, but to summarize,SpringBoot is mainly started by instantiating the SpringApplication. The startup process does the following things: Configure properties, obtain listeners, publish the application start event, initialize input parameters, configure the environment, output banner, create context, preprocess context, refresh context, refresh context, publish the application start event, publish the application start completion event, start Tomcat in the refresh context section, Then go to Spring’s bean loading process, then go to create createWebServer, go to getTomcatWebServer, and finally find start tomcat service.

SpringBootApplication is made up of three sub-annotations, They are @Configuration, @enableAutoConfiguration, @ComponentScan, and then explain in detail the role of each annotation. The second part focuses on the startup process of SpringApplication.run, including how embedded Tomcat is started. So much for SpringBoot.

Thank you for reading.