本文基于springboot2.1.6
1 当maven引入tomcat的jar依赖时
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
1.1
ServletWebServerFactoryConfiguration类中,TomcatServletWebServerFactory 会被作为bean被spring管理起来。
根据注解@ConditionalOnClass。。条件,因为没有引入jetty相关的jar,spring中不会有JettyServletWebServerFactory这个bean。
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
//转载请标明链接:https://blog.csdn.net/wabiaozia/article/details/95886191
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyServletWebServerFactory JettyServletWebServerFactory() {
return new JettyServletWebServerFactory();
}
}
1.2
ServletWebServerApplicationContext类在使用getWebServerFactory方法获得servlet容器时
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
返回对于指定类型(ServletWebServerFactory)Bean(包括子类)的所有名字。
ServletWebServerFactory的子类:JettyServletWebServerFactory,TomcatServletWebServerFactory,UndertowServletWebServerFactory,但是
只引入了tomcat的jar,所以只能获得TomcatServletWebServerFactory
。
2 源码分析
2.1 首先从main函数开始
//main 函数
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
//点击run
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
//继续点击run
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
//run
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
//略。。。。。
refreshContext(context);//点击进入。。。。。。。。。。。
afterRefresh(context, applicationArguments);
//略。。。。
return context;
}
2.2 点击refreshContext(context);方法
点击–>refresh(context);–>((AbstractApplicationContext) applicationContext).refresh();–>进入类AbstractApplicationContext的refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//略。。。。
//转载请标明链接:https://blog.csdn.net/wabiaozia/article/details/95886191
onRefresh();//点击进入
//略
}
}
2.3 进入类ServletWebServerApplicationContext的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();
}
2.4 createWebServer()方法里
//2.4.1 点击进入
ServletWebServerFactory factory = getWebServerFactory();
//2.4.2点击进入
this.webServer = factory.getWebServer(getSelfInitializer());
2.4.1 getWebServerFactory() 根据上文1.1里结论会返回TomcatServletWebServerFactory。所以2.4.2的
factory.getWebServer(getSelfInitializer())中的factory是指TomcatServletWebServerFactory
,点击进入实现类TomcatServletWebServerFactory的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);//点击进入。。。。。。。。
}
//点击进入getTomcatWebServer(tomcat)
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0);//点击进入
}
//点击new TomcatWebServer
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart;
initialize();//点击进入
}
//点击进入
private void initialize() throws WebServerException {
logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
synchronized (this.monitor) {
try {
// 略。。。。。。。
//转载请标明链接:https://blog.csdn.net/wabiaozia/article/details/95886191
this.tomcat.start();//。。。。启动tomcat
// We can re-throw failure exception directly in the main thread
rethrowDeferredStartupExceptions();
try {
ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
//略。。。。。。。。。。。。。。
}
}
2.5 见源码this.tomcat.start();这行,启动tomcat
3 至此已分析完成
转载请标明链接:
https://blog.csdn.net/wabiaozia/article/details/95886191
4 如果使用jetty要注意排除tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- SpringBoot默认使用tomcat ,若使用Jetty,要在spring-boot-starter-web排除spring-boot-starter-tomcat-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>