Back to Javatutorial

SpringBootWeb应用(二):WebMvc装配过程

docs/Spring全家桶/SpringBoot源码解析/SpringBootWeb应用(二):WebMvc装配过程.md

1.0.026.5 KB
Original Source

ƽʱУspringboot е web ĿĽ springboot Զ springMvc Ŀ̡

1. springMvc Զװ

springMvc ԶװΪ

@Configuration(proxyBeanMethods = false)
// װ
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
// ûԶWebMvc࣬ʹñ
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
// װ˳
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ 
        // DispatcherServlet Զװ
        DispatcherServletAutoConfiguration.class, 
        // ̳߳صԶװ
        TaskExecutionAutoConfiguration.class,
        // jsr 303 ֤ܵԶװ
        ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
    ...
}

@AutoConfigureAfter עУWebMvcAutoConfiguration Ҫ DispatcherServletAutoConfiguration``TaskExecutionAutoConfiguration``ValidationAutoConfiguration װ֮װ䣬Що£

  • DispatcherServletAutoConfiguration``DispatcherServlet Զװ
  • TaskExecutionAutoConfigurationִʵǴһ̳߳
  • ValidationAutoConfigurationjsr 303 ֤Զװ䣬֤ @NotNull``@NotEmpty ע֤

3 У springMvc йصֻ DispatcherServletAutoConfigurationʶһ

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
// Ҫ ServletWebServerFactoryAutoConfiguration Զװɺ
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
    ...
}

DispatcherServletAutoConfiguration Ҫ ServletWebServerFactoryAutoConfiguration ԶװɲŽװ䣬ʲôأ͸£Ǵ servlet tomcat, jetty, undertow ȣɵģ ServletWebServerFactoryAutoConfiguration

@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
// һЩ
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
        // 3 web 
        ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
        ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
        ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
    ...
}

Կû @AutoConfigureAfter עˣ springMvc Զװ࣬ǵķʹ࿪ʼ

ܽϼװ˳

  1. ServletWebServerFactoryAutoConfiguration
  2. DispatcherServletAutoConfiguration
  3. WebMvcAutoConfiguration

ǵķҲ˳һЩԶװࡣ

2. ServletWebServerFactoryAutoConfiguration Զװ

ServletWebServerFactoryAutoConfiguration £

@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
// һЩ
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
        // 3 web 
        ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
        ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
        ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
    ...
}

BeanPostProcessorsRegistrar``EmbeddedTomcat``EmbeddedJetty``EmbeddedUndertowһɣ

2.1 BeanPostProcessorsRegistrar

BeanPostProcessorsRegistrar ServletWebServerFactoryAutoConfiguration ڲ࣬£

public static class BeanPostProcessorsRegistrar 
        implements ImportBeanDefinitionRegistrar, BeanFactoryAware {

    ...

    /**
     *  ImportBeanDefinitionRegistrar ķ
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
            BeanDefinitionRegistry registry) {
        if (this.beanFactory == null) {
            return;
        }
        // ע
        registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
                WebServerFactoryCustomizerBeanPostProcessor.class);
        registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
                ErrorPageRegistrarBeanPostProcessor.class);
    }

    /**
     * ע
     */
    private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, 
            String name, Class<?> beanClass) {
        if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
            beanDefinition.setSynthetic(true);
            registry.registerBeanDefinition(name, beanDefinition);
        }
    }
}

Ҫ spring עࣺWebServerFactoryCustomizerBeanPostProcessor``ErrorPageRegistrarBeanPostProcessorǷֱǸɶ

1. WebServerFactoryCustomizerBeanPostProcessor

WebServerFactoryCustomizerBeanPostProcessor Ĵ£

public class WebServerFactoryCustomizerBeanPostProcessor 
        implements BeanPostProcessor, BeanFactoryAware {

    ...

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
            throws BeansException {
        // bean  WebServerFactory Ŵ
        if (bean instanceof WebServerFactory) {
            postProcessBeforeInitialization((WebServerFactory) bean);
        }
        return bean;
    }

    @SuppressWarnings("unchecked")
    private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
        LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
                .withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
                // 
                .invoke((customizer) -> customizer.customize(webServerFactory));
    }

    /**
     * ȡ WebServerFactoryCustomizerõһɱ List
     */
    private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
        if (this.customizers == null) {
            this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
            this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
            this.customizers = Collections.unmodifiableList(this.customizers);
        }
        return this.customizers;
    }

    /**
     * ȡ beanFactory е WebServerFactoryCustomizer
     */
    private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
        return (Collection) this.beanFactory.getBeansOfType(
                WebServerFactoryCustomizer.class, false, false).values();
    }

}

WebServerFactory Զõģʵ BeanPostProcessor Ҫע postProcessBeforeInitialization(...)

WebServerFactoryCustomizerBeanPostProcessor postProcessBeforeInitialization(...) Уǰ bean WebServerFactoryȻȡ beanFactory Ϊ WebServerFactoryCustomizer beanȻЩ WebServerFactoryCustomizer õ WebServerFactorybean С

ҪԶ Tomcat ã

@Component
public class MyCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.setPort(8091);
        factory.setContextPath("/");
        // 
        ...
    }

}

ServletWebServerFactoryAutoConfigurationWebServerFactoryCustomizer:

public class ServletWebServerFactoryAutoConfiguration {

    @Bean
    public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(
            ServerProperties serverProperties) {
        return new ServletWebServerFactoryCustomizer(serverProperties);
    }

    @Bean
    @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
    public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
            ServerProperties serverProperties) {
        return new TomcatServletWebServerFactoryCustomizer(serverProperties);
    }

    ...

}

ӷö ServerProperties

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
    ...
}

ConfigurationProperties ע⣬prefix Ϊ "server"ö server ͷֵ֧£

磬ҪĶ˿ڣֻ application.properties üɣ

server.port=8080

ãͲˡ

2. ErrorPageRegistrarBeanPostProcessor

ErrorPageRegistrarBeanPostProcessor Ĵ£

public class ErrorPageRegistrarBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {

    /**
     * BeanPostProcessorķbeanʼǰִ
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
            throws BeansException {
        if (bean instanceof ErrorPageRegistry) {
            //  bean  ErrorPageRegistry
            postProcessBeforeInitialization((ErrorPageRegistry) bean);
        }
        return bean;
    }

    private void postProcessBeforeInitialization(ErrorPageRegistry registry) {
        for (ErrorPageRegistrar registrar : getRegistrars()) {
            // עҳ
            registrar.registerErrorPages(registry);
        }
    }

    private Collection<ErrorPageRegistrar> getRegistrars() {
        if (this.registrars == null) {
            // ȡеĴҳ
            this.registrars = new ArrayList<>(this.beanFactory.getBeansOfType(
                    ErrorPageRegistrar.class, false, false).values());
            this.registrars.sort(AnnotationAwareOrderComparator.INSTANCE);
            this.registrars = Collections.unmodifiableList(this.registrars);
        }
        return this.registrars;
    }

    ...
}

Ҫע postProcessBeforeInitialization ̣

  1. bean ErrorPageRegistryе 2
  2. ȡ beanFactory ErrorPageRegistrar ͵ beanе 3
  3. registrar.registerErrorPages(registry) дҳ

Ҫ˵

  • ErrorPageRegistrarҳע ErrorPageRegistry ɻࣩ
  • ErrorPageRegistryעࣨʵʸɻࣩ

ҪԶҳʵ ErrorPageRegistry ӿڣ

@Component
public class MyErrorPage implements ErrorPageRegistrar {

    /**
     * עҳ
     */
    @Override
    public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
        // յõ ErrorPageRegistry#addErrorPages ע
        errorPageRegistry.addErrorPages(new ErrorPage("/error/page"));
    }
}

2.2 EmbeddedTomcat

ServletWebServerFactoryConfiguration.EmbeddedTomcat

@Configuration(proxyBeanMethods = false)
class ServletWebServerFactoryConfiguration {

    @Configuration(proxyBeanMethods = false)
    // ע⣬ʱ
    @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
    // ע ServletWebServerFactoryǿʵ tomcat װ
    @ConditionalOnMissingBean(value = ServletWebServerFactory.class, 
        search = SearchStrategy.CURRENT)
    public static class EmbeddedTomcat {

        @Bean
        public TomcatServletWebServerFactory tomcatServletWebServerFactory(
                ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
                ObjectProvider<TomcatContextCustomizer> contextCustomizers,
                ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
            TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
            // һЩ
            factory.getTomcatConnectorCustomizers()
                    .addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
            factory.getTomcatContextCustomizers()
                    .addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
            factory.getTomcatProtocolHandlerCustomizers()
                    .addAll(protocolHandlerCustomizers.orderedStream()
                    .collect(Collectors.toList()));
            return factory;
        }

    }

    ...
}

ҪǷ TomcatServletWebServerFactory beanעһЩ connectorCustomizers``contextCustomizers``protocolHandlerCustomizers ȲԶãЩǴ BeanPostProcessorsRegistrar ġ

иطҪһ£ʹ springboot ṩ TomcatServletWebServerFactoryǿԼʵ TomcatServletWebServerFactory

@Bean
public ServletWebServerFactory servletWebServerFactory() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    // Զĸ
    ...
    return tomcat;
}

֮springboot ṩ tomcatServletWebServerFactory Ͳᴦˡ

EmbeddedJetty``EmbeddedUndertow EmbeddedTomcat ĴƣͲ˵ˡ

3. DispatcherServletAutoConfiguration

DispatcherServletAutoConfigurationؼ£

public class DispatcherServletAutoConfiguration {

    public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

    public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME 
            = "dispatcherServletRegistration";

    @Configuration(proxyBeanMethods = false)
    @Conditional(DefaultDispatcherServletCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class })
    protected static class DispatcherServletConfiguration {

        /**
         *  DispatcherServlet.
         * @param httpProperties http.
         * @param webMvcProperties webMvc .
         * @return ض
         */
        @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;
        }

        /**
         * ļϴ.
         * @param resolver .
         * @return ֵ.
         */
        @Bean
        @ConditionalOnBean(MultipartResolver.class)
        @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
        public MultipartResolver multipartResolver(MultipartResolver resolver) {
            return resolver;
        }

    }

    /**
     *  DispatcherServletRegistrationBean
     * ὫdispatcherServletעᵽservlet
     */
    @Configuration(proxyBeanMethods = false)
    @Conditional(DispatcherServletRegistrationCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties(WebMvcProperties.class)
    @Import(DispatcherServletConfiguration.class)
    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ὫdispatcherServletעᵽservlet
            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;
        }

    }

    ...

}

Ҫע 3 bean

  • dispatcherServletspringMvc ڣurl ɴ˽룬Ȼת requestMapping
  • multipartResolverļϴ
  • dispatcherServletRegistration dispatcherServlet עᣬὫ dispatcherServlet עᵽ servlet У springboot ע servlet ݣԲο springboot web Ӧ֮ servlet ע

4. WebMvcAutoConfiguration

WebMvcAutoConfiguration:

@Configuration(proxyBeanMethods = false)
...
// ûԶWebMvc࣬ʹñ
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
...
public class WebMvcAutoConfiguration {
    ...
}

WebMvcAutoConfiguration иעҪע£

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

д WebMvcAutoConfiguration ֻ WebMvcConfigurationSupport ͵ bean ʱŻԶװ䡣

WebMvcConfigurationSupport Ǹɶأ springmvc demo @EnableWebMvc עһУᵽ springMvc ַʽ

  • ʹ @EnableWebMvc ע
  • ̳ WebMvcConfigurationSupport

ַն spring Ϊ WebMvcConfigurationSupport bean springboot ĿУǽֲ֮һô WebMvcConfigurationSupport``WebMvcAutoConfiguration ԶװͲִˡ

WebMvcAutoConfiguration װ bean

4.1 WebMvcAutoConfigurationAdapter

WebMvcAutoConfigurationAdapter WebMvcAutoConfiguration ڲ࣬£

@Configuration(proxyBeanMethods = false)
//  EnableWebMvcConfiguration
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    ...
}

ʵ WebMvcConfigurer EnableWebMvcConfiguration``WebMvcConfigurer springMvc ãֻҪджӦķɣEnableWebMvcConfiguration webMvc áҲ WebMvcAutoConfiguration ڲ࣬ɶ

@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration 
        implements ResourceLoaderAware {
    ...
}

Կ DelegatingWebMvcConfigurationDelegatingWebMvcConfiguration ǸɶأҲĶ壺

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    ...
}

DelegatingWebMvcConfiguration springMvc ṩģԿʵ WebMvcConfigurationSupportˣspringboot ͨ @Import(EnableWebMvcConfiguration.class) ķʽ spring WebMvcConfigurationSupport ͵ bean

ʵϣDelegatingWebMvcConfiguration @EnableWebMvc bean

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
//  DelegatingWebMvcConfiguration
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
    ...
}

springbot ֱ DelegatingWebMvcConfiguration EnableWebMvcConfigurationȻһЩԶõġ

EnableWebMvcConfiguration Щɶһٷ WebMvcAutoConfigurationAdapter bean

/**
 * http Ϣת.
 */
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    this.messageConvertersProvider.ifAvailable(
            (customConverters) -> converters.addAll(customConverters.getConverters()));
}

/**
 * ͼ.
 */
@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix(this.mvcProperties.getView().getPrefix());
    resolver.setSuffix(this.mvcProperties.getView().getSuffix());
    return resolver;
}

@Bean
@ConditionalOnBean(View.class)
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
    BeanNameViewResolver resolver = new BeanNameViewResolver();
    resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
    return resolver;
}

@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
    ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
    resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
    resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return resolver;
}

/**
 * ʻ.
 */
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
    if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
        return new FixedLocaleResolver(this.mvcProperties.getLocale());
    }
    AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
    localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
    return localeResolver;
}

/**
 * ̬Դӳ
 */
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
        return;
    }
    // ӳwebjars
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache()
            .getCachecontrol().toHttpCacheControl();
    if (!registry.hasMappingForPattern("/webjars/**")) {
        customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/")
                .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
    // ӳ侲̬Դ·
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
        customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
                // staticLocations ĬΪ classpath:[/META-INF/resources/,
                // /resources/, /static/, /public/]
                .addResourceLocations(getResourceLocations(
                    this.resourceProperties.getStaticLocations()))
                .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
}

ԿWebMvcAutoConfigurationAdapter bean:

  1. http Ϣת
  2. ͼ
  3. ʻ

ص httpϢתʹ springMvc ʱͨ Controller еķϱ @ResponseBodyزͻתΪ json httpϢתĹˡspringboot Ĭϵ jaon jacksonʵ JacksonAutoConfiguration УװΪ HttpMessageConverter Ĵ JacksonHttpMessageConvertersConfigurationͲչˡ

ķУγ WebMvcProperties ãǸɶ

@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
    ...
}

ԣǸ Կǰ׺Ϊ spring.mvcֵ֧£

4.2 EnableWebMvcConfiguration

EnableWebMvcConfiguration Զã

public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration 
        implements ResourceLoaderAware {

    /**
     * 
     */
    @Bean
    @Override
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
            @Qualifier("mvcContentNegotiationManager") 
                ContentNegotiationManager contentNegotiationManager,
            @Qualifier("mvcConversionService") FormattingConversionService conversionService,
            @Qualifier("mvcValidator") Validator validator) {
        RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(
                contentNegotiationManager, conversionService, validator);
        adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null 
                || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
        return adapter;
    }

    /**
     * ·ӳ
     */
    @Bean
    @Primary
    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping(
            @Qualifier("mvcContentNegotiationManager") 
                    ContentNegotiationManager contentNegotiationManager,
            @Qualifier("mvcConversionService") FormattingConversionService conversionService,
            @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
        // Must be @Primary for MvcUriComponentsBuilder to work
        return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService,
                resourceUrlProvider);
    }

    /**
     * ӭҳ
     */
    @Bean
    public WelcomePageHandlerMapping welcomePageHandlerMapping(
            ApplicationContext applicationContext, 
            FormattingConversionService mvcConversionService, 
            ResourceUrlProvider mvcResourceUrlProvider) {
        WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
                new TemplateAvailabilityProviders(applicationContext), applicationContext, 
                getWelcomePage(), this.mvcProperties.getStaticPathPattern());
        welcomePageHandlerMapping.setInterceptors(getInterceptors(
                mvcConversionService, mvcResourceUrlProvider));
        return welcomePageHandlerMapping;
    }

    /**
     * mvcãڸʽĴ
     */
    @Bean
    @Override
    public FormattingConversionService mvcConversionService() {
        WebConversionService conversionService 
            = new WebConversionService(this.mvcProperties.getDateFormat());
        addFormatters(conversionService);
        return conversionService;
    }

    /**
     * У
     */
    @Bean
    @Override
    public Validator mvcValidator() {
        if (!ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) {
            return super.mvcValidator();
        }
        return ValidatorAdapter.get(getApplicationContext(), getValidator());
    }

    /**
     * 쳣
     */
    @Override
    protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() {
        if (this.mvcRegistrations != null 
                && this.mvcRegistrations.getExceptionHandlerExceptionResolver() != null) {
            return this.mvcRegistrations.getExceptionHandlerExceptionResolver();
        }
        return super.createExceptionHandlerExceptionResolver();
    }

    @Override
    protected void extendHandlerExceptionResolvers(
                List<HandlerExceptionResolver> exceptionResolvers) {
        super.extendHandlerExceptionResolvers(exceptionResolvers);
        if (this.mvcProperties.isLogResolvedException()) {
            for (HandlerExceptionResolver resolver : exceptionResolvers) {
                if (resolver instanceof AbstractHandlerExceptionResolver) {
                    ((AbstractHandlerExceptionResolver) resolver).setWarnLogCategory(
                            resolver.getClass().getName());
                }
            }
        }
    }
    ...
}

ԭ springMvc·ӳ䡢У顢쳣ȡ

5. ܽ

  1. webMvc װʱװ ServletWebServerFactoryAutoConfigurationװ DispatcherServletAutoConfigurationװ WebMvcAutoConfiguration
  2. ServletWebServerFactoryAutoConfiguration servlet װ䣬DispatcherServletAutoConfiguration DispatcherServlet װ䣬WebMvcAutoConfiguration webMvc Ϣתͼ̬Դӳȣװ
  3. spring WebMvcConfigurationSupport WebMvcAutoConfiguration װִ
  4. servlet servlet Ϊǰ׺webMvc spring.mvc Ϊǰ׺ǿļһΪ application.properties/application.ymlн

ԭӣhttps://my.oschina.net/funcy/blog/4921595 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע