- 回顾SpringMVC发送请求的配置
- 可以先看看Servlet的结构图
- SpringBoot中能实现请求接收发送必须具备条件
- 源码剖析的追踪问题
- 问题一
- 问题二
- DispatcherServletRegistrationBean的类图
- 1、从顶层接口 ServletContextInitializer 看
- 2、安装类图找子类RegistrationBean
- 3、按照类图查找
- 4、继续进入
- 5、根据类图往下找
- 6、将DispatcherServlet添加到servletContext中
- 接下来分析如何去调用得到这个addRegistration方法的呢?
- 1、进入getSelfInitializer
- ">2、进入getSelfInitializer方法的selfInitialize方法
- 3、进入接口的onStartup方法
- 4、调用实现类
- 5、继续调用到子类
- 6、将其放入到容器中
- 总结
回顾SpringMVC发送请求的配置
在SpringBoot 项目里面是可以直接使用诸如 @RequestMapping 这类的SpringMVC的注解,那么这是为什么?我明明没有配置SpringMVC为什么就可以使用呢?
其实仅仅引入starter是不够的,回忆一下,在一个普通的WEB项目中如何去使用SpringMVC,首先就是要在web.xml中配置如下配置 DispatcherServlet 这个Servlet。
<servlet>
<description>spring mvc servlet</description>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
但是在SpringBoot中,并没有web.xml文件,又是如何去配置一个 Dispatcherservlet 呢? 其实Servlet3.0规范中规定,要添加一个Servlet,除了采用xml配置的方式,还有一种通过代码的 方式,伪代码如下
servletContext.addServlet(name, this.servlet);
也就是说,如果要能动态往web容器中添加一个构造好的 DispatcherServlet 对象, 是不是就实现自动装配SpringMVC了
可以先看看Servlet的结构图
SpringBoot中能实现请求接收发送必须具备条件
1、通过自动配置从文件获取到 DispatcherServlet 工厂路径并进行实例化存放到IOC容器中
2、必须将 DispatcherServlet 存放到ServletContext容器中。(因为Servlet实例必须要注册到Tomcat的ServletContext中,才能够进行请求服务)
会去加载这个类,并将其类进行实例化
因为在Servlet启动的过程中,会去回调SpringServletContainerInitializer中的onStratup方法
在onStratup方法中,一步步剖析就能发现如何进行将实例注册到ServletContext的。添加后,就能进行正常的接收请求,并进行响应返回等。
源码剖析的追踪问题
第一点SpringMVC是如何通过自动装配生成实例存到IOC容器
第二点DispatcherServlet 是如何将其注册到ServletContext中的
问题一
1、从main方法的注解入手
2、进入实现自动装配的注解
3、进入自动导入的类
通过Spring底层注解@Import,给容器注入一个组件
4、经过debug发现SpringMVC的自动配置类
5、全局搜索spring.factories
6、查看DispatcherServletAutoConfiguration
6.1、看第一个内部类
6.2、看第二个内部类
第一个问题就是干这个事
问题二
在上一小节的源码翻阅中,已经看到了DispatcherServlet和DispatcherServletRegistrationBean 这两个Bean的自动配置。DispatcherServlet我们很熟悉,DispatcherServletRegistrationBean负 责将DispatcherServlet注册到ServletContext当中 。
DispatcherServletRegistrationBean的类图
然该类的职责是负责注册DispatcherServlet,那么得知道什么时候触发注册操作。为此, 我们先看看DispatcherServletRegistrationBean这个类的类图
看注册DispatcherServlet流程
1、从顶层接口 ServletContextInitializer 看
最上面是一个ServletContextInitializer接口。实现该接口意味着是用 来初始化ServletContext的。我们看看该接口。通过这个方法就可以省去xml
2、安装类图找子类RegistrationBean
3、按照类图查找
4、继续进入
再看DynamicRegistrationBean是怎么实现register方法的 ,进入 跟进addRegistration方法
5、根据类图往下找
6、将DispatcherServlet添加到servletContext中
这里直接将DispatcherServlet给add到了servletContext当中。
接下来分析如何去调用得到这个addRegistration方法的呢?
有两种分析方式:
只有知道什么时候调用的,才能知道什么时候去存吧!
回到主函数的run方法,一路进去,refreshContext-》refresh-》
然后跳到Spring容器的onRefresh方法,继续进入ServletWebServerApplicationContext#createWebServer
1、进入getSelfInitializer
因为这里能返回是服务器,那么服务器里面肯定是有ServletContext的
2、进入getSelfInitializer方法的selfInitialize方法
3、进入接口的onStartup方法
4、调用实现类
5、继续调用到子类
6、将其放入到容器中
总结
SpringBoot自动装配SpringMvc其实就是往ServletContext中加入了一个 Dispatcherservlet 。
Servlet3.0规范中有这个说明,除了可以动态加Servlet,
还可以动态加Listener,Filter addServlet addListener addFilter
还要一个方法,就是直接打断点这里,然后通过debug及调用栈进行反推
关键的一步是在从Spring源码onRefresh方法到createWebServer方法中,这步骤是关键
有时间在将时序图画出来。