前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【SpringBoot源码解析】第四章:SpringBoot是如何自动装配SpringMvc的

【SpringBoot源码解析】第四章:SpringBoot是如何自动装配SpringMvc的

原创
作者头像
诺浅
修改2020-08-21 17:47:30
6220
修改2020-08-21 17:47:30
举报
文章被收录于专栏:工具使用工具使用

缘起

在上一章中,我们介绍了SpringBoot是如何启动一个内置tomcat的。我们知道我们在SpringBoot项目里面是可以直接使用诸如@RequestMapping这类的SpringMVC的注解,那么你会不会奇怪,这是为什么?我明明没有配置SpringMVC为什么就可以使用呢?

SpringBoot是如何自动装配SpringMVC的

你还记得我们如何在一个普通的WEB项目中使用SpringMVC吗?我们首先就是要在web.xml中配置如下配置

代码语言:txt
复制
<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>

你有没有想过配置的这个东西到底是在干嘛呢?其实要说清楚这个是在干嘛,涉及到SpringMVC的底层原理,我们这里可以理解为这就是在配置一个Dispatcherservlet,这个Dispatcherservlet是可以帮我妈转发请求到其他的Servlet,理解不了没关系,我们只要知道在SpringMVC中,必须需要先配置一个Dispatcherservlet,而在SpringBoot中,我们没有了web.xml文件,我们如何去配置一个Dispatcherservlet呢?其实Serclet3.0规范中规定,要添加一个Servlet,除了采用xml配置的方式,还有一种通过代码的方式,伪代码如下

代码语言:txt
复制
servletContext.addServlet(name, this.servlet);

那么也就是说,如果我们能动态往web容器中添加一个我们构造好的DispatcherServlet对象,是不是就能实现自动装配SpringMVC了?那么SpringBoot又是什么时候把这个DispatcherServlet装载进容器的呢?下面来说

不知道在前面讲解【SpringBoot源码解析】第二章:SpringBoot是如何通过内置Tomcat启动的你有没有注意到有这样一段代码

代码语言:txt
复制
getSelfInitializer().onStartup(servletContext);

这段代码其实就是去加载SpringMVC,那么他是如何做到的呢?getSelfInitializer()最终会去调用到ServletWebServerApplicationContextselfInitialize方法,该方法代码如下

代码语言:txt
复制
private void selfInitialize(ServletContext servletContext) throws ServletException {
	prepareWebApplicationContext(servletContext);
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(
			beanFactory);
	WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,
			getServletContext());
	existingScopes.restore();
	WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,
			getServletContext());
	for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
		beans.onStartup(servletContext);
	}
}

我们通过调试,知道getServletContextInitializerBeans()返回的是一个ServletContextInitializer集合,集合中有以下几个对象

image.png
image.png

然后依次去调用对象的onStartup方法,那么对于上图标红的对象来说,就是会调用到DispatcherServletRegistrationBeanonStartup方法,这个类并没有这个方法,所以最终会调用到父类RegistrationBeanonStartup方法,该方法代码如下

代码语言:txt
复制
public final void onStartup(ServletContext servletContext) throws ServletException {
	//获取当前环境到底是一个filter 还是一个servlet 还是一个listener
	String description = getDescription();
	if (!isEnabled()) {
		logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
		return;
	}
	register(description, servletContext);
}

这边register(description, servletContext);会调用到DynamicRegistrationBeanregister方法,代码如下

代码语言:txt
复制
protected final void register(String description, ServletContext servletContext) {
	D registration = addRegistration(description, servletContext);
	if (registration == null) {
		logger.info(StringUtils.capitalize(description) + " was not registered (possibly already registered?)");
		return;
	}
	configure(registration);
}

addRegistration(description, servletContext)又会调用到ServletRegistrationBean中的addRegistration方法,代码如下

代码语言:txt
复制
protected ServletRegistration.Dynamic addRegistration(String description, ServletContext servletContext) {
  String name = getServletName();
  return servletContext.addServlet(name, this.servlet);
}

看到了关键的servletContext.addServlet代码了把,我们通过调试,即可知到this.servlet就是dispatcherServlet

image.png
image.png

总结

SpringBoot自动装配SpringMvc其实就是往ServletContext中加入了一个Dispatcherservlet

Serclet3.0规范中有这个说明,除了可以动态加Servlet,还可以动态加Listener,Filter

  • addServlet
  • addListener
  • addFilter

到此为止,还有一个问题,那便是springboot是如何加装其他应用的呢?我们知道,比如我们要在项目里面使用Feign,我们只需要使用这样一个注解@EnableFeignClients.那么这是如何做到的呢?

其实这涉及到如何在springboot中自定义starter

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 缘起
  • SpringBoot是如何自动装配SpringMVC的
  • 总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档