SpringBoot启动原理

启动内置Tomcat原理

从SpringApplication.run进入

/*
SpringApplication > run()
*/
......
try {
   ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
   ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
   configureIgnoreBeanInfo(environment);
   Banner printedBanner = printBanner(environment);
    //创建web容器或者普通IOC容器
   context = createApplicationContext();
   exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
         new Class[] { ConfigurableApplicationContext.class }, context);
   prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    //刷新容器
   refreshContext(context);
   afterRefresh(context, applicationArguments);
   stopWatch.stop();
   if (this.logStartupInfo) {
      new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
   }
   listeners.started(context);
   callRunners(context, applicationArguments);
}
......

从refreshContext进入,会一直调到AbstartApplicationContext的refresh()方法

/*
AbstartApplicaionContext > refresh()
*/
......
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
//注册自定义的beanDefinition,并执行BeanFactory和BeanDefinition后置处理器方法
//这里会BeanFactory的后置处理器方法,完成springBoot属性自动注入
invokeBeanFactoryPostProcessors(beanFactory);

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

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

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

// Initialize other special beans in specific context subclasses.
//本来是一个空方法,但ServletWebServerApplicationContext实现了这个方法,并且在这里完成对Tomcat的启动
onRefresh();

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

// Instantiate all remaining (non-lazy-init) singletons.
//对ben进行初始化
finishBeanFactoryInitialization(beanFactory);

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

进入onRefresh方法中

/*
ServletWebServerApplicaionContext > onRefresh()
*/
@Override
protected void onRefresh() {
   super.onRefresh();
   try {
      createWebServer();
   }
   catch (Throwable ex) {
      throw new ApplicationContextException("Unable to start web server", ex);
   }
}
/*
ServletWebServerApplicaionContext > createWebServer()
*/
private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
            //获取对应的webServer工厂,并调用自动装配好的容器自定义定制器
			ServletWebServerFactory factory = getWebServerFactory();
            //获取Tomcat对象
			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();
	}

进入getWebServer方法,完成对内置Tomcat创建和启动

/*
TomcatServletWebServletFactory > getWebServer()
*/
@Override
	public WebServer getWebServer(ServletContextInitializer... initializers) {
		if (this.disableMBeanRegistry) {
			Registry.disableRegistry();
		}
        //创建Tomcat
		Tomcat tomcat = new Tomcat();
		File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
        //配置Tomcat
		tomcat.setBaseDir(baseDir.getAbsolutePath());
		Connector connector = new Connector(this.protocol);
		connector.setThrowOnFailure(true);
		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);
	}

从getTomcatWebServer方法进去,最后调用initialize方法完成对Tomcat启动

/*
TomcatWebServer > initialize()
*/
// Start the server to trigger initialization listeners
//启动Tomcat
this.tomcat.start();

// We can re-throw failure exception directly in the main thread
//创建一个守护线程
rethrowDeferredStartupExceptions();

try {
   ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
catch (NamingException ex) {
   // Naming is not enabled. Continue
}
posted @ 2020-11-29 20:34  zcr小翟  阅读(83)  评论(0编辑  收藏  举报