SpringBoot是如何集成了Tomcat呢?

    我们肯定对SpringBoot默认内部集成了Tomcat web环境不陌生,虽然reactive容器逐渐崭露头角,但相信大部分的用户还是使用了Tomcat的容器的。不知道是否有同学和我一样,对SpringBoot如何集成了tomcat有好奇,这里我们从springboot的源码中查看一下,它是如何集成tomcat的;

    先来看springboot的标准启动的代码:

SpringApplication.run(SpringBootApplication.class, args);

1. 首先,同名run方法中:

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

可以找到创建了SpringApplication对象的代码,从构造方法我们可以找到一个关键点:

this.webApplicationType = WebApplicationType.deduceFromClasspath();

deduceFromClasspath方法会从环境里是否有特定的类来判断WebApplicationType,由于我们没有配置reactive,因此此处会返回WebApplicationType.SERVLET

2. 分析完构造方法之后,我们来看一下run方法的内部,其中有一行:

context = createApplicationContext();

这个方法就会根据上一步的WebApplicationType来决定上下文;在这里我们会执行到

contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);

3. webServer的创建入口

webServer的创建是在run方法的refreshContext中的。

经过几个跳转我们来到了十分熟悉的,十分出名的 AbstractApplicationContext # refresh方法,重点关注它的onRefresh

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

其中有一个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();
	}

这个方法先会创建一个webServer工厂类,默认情况下,就是TomcatServletWebServerFactory了!

我们看下它的getWebServer方法:

	@Override
	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);
	}

哈哈,成功找到了。

createWebServer接下来会设置webServer属性,最后调用initPropertySources方法(如果环境中存在servletContextInitParams/servletConfigInitParams属性,会对其进行一个替换),并不是关注的重点,我们先跳过;

4. 我们跟踪到AbstractApplicationContext # refresh -> finishRefresh方法:

	@Override
	protected void finishRefresh() {
		super.finishRefresh();
		WebServer webServer = startWebServer();
		if (webServer != null) {
			publishEvent(new ServletWebServerInitializedEvent(webServer, this));
		}
	}

这里会启动WebServer

	private WebServer startWebServer() {
		WebServer webServer = this.webServer;
		if (webServer != null) {
			webServer.start();
		}
		return webServer;
	}

在默认情况下,我们就会调用到TomcatWebServer方法了;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值