首页 > 文章列表 > Springboot自动装配之注入DispatcherServlet怎么实现

Springboot自动装配之注入DispatcherServlet怎么实现

springboot dispatcherservlet
300 2023-05-19

Springboot自动装配之注入DispatcherServlet怎么实现

原理概述

Springboot向外界提供web服务,底层依赖了springframework中的web模块(包含但不限于spring mvc核心类DispatcherServlet)来实现

那么springboot在什么时机向容器注入DispatcherServlet这个核心类的呢

注入的流程还是遵循了自动装配流程,在springboot框架里默认提供了该自动装配的支持

在jar包里的spring.factories文件里有个 org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration配置

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)

@Configuration(proxyBeanMethods = false)

@ConditionalOnWebApplication(type = Type.SERVLET)

@ConditionalOnClass(DispatcherServlet.class)

@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)

public class DispatcherServletAutoConfiguration {

	/*

	 * The bean name for a DispatcherServlet that will be mapped to the root URL "/"

	 */

	public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

	/*

	 * The bean name for a ServletRegistrationBean for the DispatcherServlet "/"

	 *

	public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";

	// ... 省略代码

	}

在DispatcherServletAutoConfiguration中有两个内部类(配置类) DispatcherServletConfiguration、DispatcherServletRegistrationConfiguration和两个对应的Condition类DefaultDispatcherServletCondition、DispatcherServletRegistrationCondition

DispatcherServletConfiguration

DispatcherServletConfiguration是DispatcherServletAutoConfiguration 的一个内部类,并被 @Configuration标注,会被容器自动扫描到;其有两个方法: 1、dispatcherServlet;2、multipartResolver

	@Configuration(proxyBeanMethods = false)

	@Conditional(DefaultDispatcherServletCondition.class)

	@ConditionalOnClass(ServletRegistration.class)

	@EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class })

	protected static class DispatcherServletConfiguration {



// @A

		@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)

		public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {

			DispatcherServlet dispatcherServlet = new DispatcherServlet();

			dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());

			dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());

			dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());

			dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());

			dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails());

			return dispatcherServlet;

		}



// @B

		@Bean

		@ConditionalOnBean(MultipartResolver.class)

		@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)

		public MultipartResolver multipartResolver(MultipartResolver resolver) {

			// Detect if the user has created a MultipartResolver but named it incorrectly

			return resolver;

		}

	}

@A:

  • @Configuration(proxyBeanMethods = false):配置类采用Lite模式

  • @Conditional(DefaultDispatcherServletCondition.class):根据DefaultDispatcherServletCondition类返回值计算是否要注入,主要逻辑是检验Spring容器中是否已经存在一个名字为"dispatcherServlet"的DispatcherServlet

  • @ConditionalOnClass(ServletRegistration.class):容器中必须要有ServletRegistration类

  • @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class }):加载HttpProperties和WebMvcProperties

@B:注入 MultipartResolver 解析类

DispatcherServletRegistrationConfiguration

该类注入的逻辑与DispatcherServletConfiguration 相同,只不过在类上注解了 @Import(DispatcherServletConfiguration.class)那么这两个类定义就有了先后顺序

@Configuration(proxyBeanMethods = false)

	@Conditional(DispatcherServletRegistrationCondition.class)

	@ConditionalOnClass(ServletRegistration.class)

	@EnableConfigurationProperties(WebMvcProperties.class)

	@Import(DispatcherServletConfiguration.class) //@A

	protected static class DispatcherServletRegistrationConfiguration {



		@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)

		@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)

		public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,

				WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {

			DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,

					webMvcProperties.getServlet().getPath());

			// 设置名称		

			registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);

			registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());

			multipartConfig.ifAvailable(registration::setMultipartConfig);

			return registration;

		}

	}

其中,DispatcherServletRegistrationBean继承自ServletRegistrationBean,主要为DispatcherServlet提供服务。DispatcherServletRegistrationBean和DispatcherServlet都提供了注册Servlet并公开DispatcherServletPath信息的功能