SpringBoot源码分析------mvc容器的创建和tomcat的启动

1.SpringApplication
我们先创建一个基本的SpringBoot项目,然后找到SpringApplication.run()方法,并且查看里面的调用。
在这里插入图片描述
我们会发现此时是再次调用了run(),点击run()方法
在这里插入图片描述
里面是new了一个SpringApplication,我们把new SpringApplication(SpringbootApplication.class).run(args);拿来替换main()方法中的SpringApplication.run(SpringbootApplication.class, args);,运行,可以发现两者的鲜果是一样的。

我们可以查看到run方法有返回值。对象类型是ConfigurableApplicationContext。这个类可以设置我们的Banner。也就是我们平常启动显示出来的这个图标
在这里插入图片描述
进入new SpringApplication(SpringbootApplication.class).run(args);的run()方法,可以查看到
在这里插入图片描述这么一段代码,为什么要把start(),stop()圈出来呢?其实我们先看看这个stopWatch是干什么的类吧。
在这里插入图片描述System.nanoTime()返回最准确的可用系统计时器的当前值,以毫微秒为单位。这也就是我们为什么在控制台可以看到有启动时间的原因,那么看到了start()和stop()也就是代表着启动结束了。我们后面再来分析这一段代码。

我们再来看到new SpringApplication(SpringbootApplication.class).run(args);这一段,看看他的执行方法,点进去他在执行run方法之前会去执行this()方法。那么我们看看this()方法。
在这里插入图片描述我们先从这里开始看

  1. this.webApplicationType = WebApplicationType.deduceFromClasspath();
    点击方法进入
    在这里插入图片描述
    其中
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";

private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";

ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) 查看是否有org.springframework.web.reactive.DispatcherHandler
之后的ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)同理。假若全部为true则使用响应式WEB启动,
如果不存在"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"则不嵌入web服务器。
否则,嵌入servlet服务器。

其实他return的数据只是进行了枚举包装
在这里插入图片描述
这张图片的内容我们也解释一下。
NONE:应用程序不应作为Web应用程序运行,也不应启动嵌入式Web服务器。
SERVLET:应用程序应作为基于servlet的Web应用程序运行,并应启动嵌入式servlet Web服务器。
REACTIVE:应用程序应作为响应式Web应用程序运行,并应启动嵌入式响应式Web服务器。

这个webApplicationType 我们也可以以自己设置,在yml中设置,如下:
在这里插入图片描述

  1. setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    默认从这两个jar包的路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
    在这里插入图片描述

  2. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    从类路径下找到META-INF/spring.factories配置的所有ApplicationListener。一般都是查询上面图片中的配置。他们两个都会扫描所有的jar包中的spring.factories

  3. this.mainApplicationClass = deduceMainApplicationClass();
    获取Main函数主类

2.@EnableAutoConfiguration
查看源码
在这里插入图片描述
借用@Import注册了AutoConfigurationImportSelector
那么我们看看AutoConfigurationImportSelector.java
在这里插入图片描述
看到这个方法getAutoConfigurationEntry()
在这里插入图片描述再看到getCandidateConfigurations()方法,点击进去可以看到
在这里插入图片描述在这里插入图片描述
getSpringFactoriesLoaderFactoryClass()方法被调用,看到SpringFactoriesLoader我们应该会很快的想到spring.factories这个文件,又是去扫描jar包里面的这个文件。我们可以去看看
在这里面
在这里插入图片描述
在这里插入图片描述
里面一共100+,其中一部分是不会被注入的,因为没有被引用。
在前面的文章我们都知道SpringMVC最重要的就是DispatcherServlet,在里面一搜索果然有关于他的。
在这里插入图片描述
里面还有一个ServletWebServerFactoryAutoConfiguration,这个也就是ServletFaactory,我们拿出来,去看看他做了什么。
在这里插入图片描述
圈出来的位置应该很熟悉了,这就是我们之前手动启动tomcat的Embedded吧?这个是后要,我们先查看这个Bean==>tomcatServletWebServerFactoryCustomizer在上述图片里面应该也有,我们看看他的底层是什么。
在这里插入图片描述
在这里插入图片描述
应该很熟悉吧?我们在yml中会经常使用到server.xxx
在这里插入图片描述

好了,现在我们再去查看刚刚提到的ServletWebServerFactoryConfiguration.EmbeddedTomcat
我们直接点击进去看。
在这里插入图片描述
他使用了@Bean注册了tomcatServletWebServerFactory,我们去看看这个被注册的bean,找到getWebServer()方法
在这里插入图片描述
这里应该很熟悉了。这里我们在手动启动tomcat的时候和这个操作差不多。这里就是启动tomcat,我们在创建这一部分打个断点。(后续使用)

我们在回来查看DispatcherServletAutoConfiguration这个bean。点击进去
在这里插入图片描述
这里我们可以找到DispatcherServletConfiguration,可以看到使用了@Bean,直接注册了DispatcherServlet
在这里插入图片描述
我们在此方法中随意打个断点。现在我们来思考,是DispatcherServlet先创建还是先启动tomcat,我们直接Debug,我们会发现会先启动Tomcat然后在去创建DispatcherServlet

猜你喜欢

转载自blog.csdn.net/weixin_43911969/article/details/115058311