【springboot源码解析】第三章:springboot是如何自动装配springmvc的

缘起

在上一章中,我们介绍了springboot是如何启动一个内置tomcat的,看完之后你可能还有疑问,那么我的springmvc是什么时候配置的呢?为什么我在项目理解价格@requestMapping就能接收对应的请求呢?

springboot是如何自动装配springmvc的

我们知道,springmvc中最主要的就是Dispatcherservlet,也就是说,如果我们能动态往web容器中添加这么一个servlet,那么就能实现自动装配springmvc了,那么springboot又是什么时候把这个dispatcherServlet装载进容器的呢?
不知道在前面一章的讲解在tomcat启动过程中你有没有注意到有这样一段代码

getSelfInitializer().onStartup(servletContext);

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

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集合,集合中有以下几个对象
【springboot源码解析】第三章:springboot是如何自动装配springmvc的_第1张图片
然后依次去调用对象的onStartup方法,那么对于上图标红的对象来说,就是会调用到DispatcherServletRegistrationBean的onStartup方法,这个类并没有这个方法,所以最终会调用到父类RegistrationBean的onStartup方法,该方法代码如下

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);会调用到DynamicRegistrationBean的register方法,代码如下

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方法,代码如下

protected ServletRegistration.Dynamic addRegistration(String description, ServletContext servletContext) {
  String name = getServletName();
  return servletContext.addServlet(name, this.servlet);
}

我们通过调试,即可知到this.servlet就是dispatcherServlet
【springboot源码解析】第三章:springboot是如何自动装配springmvc的_第2张图片

看到这里明白了吧?

总结

springboot自动装配springmvc其实就是往servletContext中加入了一个dispatcherservlet。
什么?Servlet还可以这样注入的吗?是的,Serclet3.0规范中有这个说明,除了可以动态加Servlet,还可以动态加Listener,Filter

  • addServlet
  • addListener
  • addFilter

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

其实这涉及到如何在springboot中自定义starter,我有一篇文章,里面有写
SpringBoot自定义starter

你可能感兴趣的:(SpringBoot)