1. 程式人生 > 其它 >springboot如何一步步啟動內建的tomcat(工廠模式的典型應用)

springboot如何一步步啟動內建的tomcat(工廠模式的典型應用)

下面跟隨原始碼一步步找到如何啟動內建的tomcat(springboot版本為2.1.2):

1、啟動類

@EnableTransactionManagement
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(RuoYiApplication.class, args);
    }
}

2、跟入run方法:

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

3、跟入refreshContext方法:

private void refreshContext(ConfigurableApplicationContext context) {
        refresh(context);
        
if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } }
protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
        ((AbstractApplicationContext) applicationContext).refresh();
    }
public void refresh() throws BeansException, IllegalStateException {
                ...
                // Initialize other special beans in specific context subclasses.
                onRefresh();
                ...
    }

4、進入子類(ServletWebServerApplicationContext)的onRefresh方法:

    @Override
    protected void onRefresh() {
        super.onRefresh();
        try {
            createWebServer();
        }
        catch (Throwable ex) {
            throw new ApplicationContextException("Unable to start web server", ex);
        }
    }

5、進入createWebServer方法:

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

6、進入getWebServerFactory方法:

protected ServletWebServerFactory getWebServerFactory() {
        // Use bean names so that we don't consider the hierarchy
        String[] beanNames = getBeanFactory()
                .getBeanNamesForType(ServletWebServerFactory.class);
        if (beanNames.length == 0) {
            throw new ApplicationContextException(
                    "Unable to start ServletWebServerApplicationContext due to missing "
                            + "ServletWebServerFactory bean.");
        }
        if (beanNames.length > 1) {
            throw new ApplicationContextException(
                    "Unable to start ServletWebServerApplicationContext due to multiple "
                            + "ServletWebServerFactory beans : "
                            + StringUtils.arrayToCommaDelimitedString(beanNames));
        }
        return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }

7、springboot中預設注入了tomcat的工廠,即TomcatServletWebServerFactory,繼續,進入factory.getWebServer(getSelfInitializer()):

public WebServer getWebServer(ServletContextInitializer... initializers) {
        Tomcat 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);
        }
        prepareContext(tomcat.getHost(), initializers);
        return getTomcatWebServer(tomcat);
    }

8、最終返回TomcatWebServer。

總結:

基本啟動流程如上所述。

另外獲取server工廠,並使用具體的工廠建立tomcatserver的方式是一個典型的工廠設計模式。