Spring Boot Spring MVC's automatic configuration

Official website Description

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

Automatic Configuration of the ViewRenderer.
Direct search in this class in WebMvcAutoConfiguration.

@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));
    // ContentNegotiatingViewResolver uses all the other view resolvers to locate
    // a view so it should have a high precedence
    resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return resolver;
}

Enter ContentNegotiatingViewResolver class, find initialization method:

protected void initServletContext(ServletContext servletContext) {
    Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
    ViewResolver viewResolver;
    if (this.viewResolvers == null) {
        this.viewResolvers = new ArrayList(matchingBeans.size());
        Iterator var3 = matchingBeans.iterator();

        while(var3.hasNext()) {
            viewResolver = (ViewResolver)var3.next();
            if (this != viewResolver) {
                this.viewResolvers.add(viewResolver);
            }
        }
    } else {
        for(int i = 0; i < this.viewResolvers.size(); ++i) {
            viewResolver = (ViewResolver)this.viewResolvers.get(i);
            if (!matchingBeans.contains(viewResolver)) {
                String name = viewResolver.getClass().getName() + i;
                this.obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(viewResolver, name);
            }
        }
    }

    AnnotationAwareOrderComparator.sort(this.viewResolvers);
    this.cnmFactoryBean.setServletContext(servletContext);
}

It found that all the items in the view resolver are grouped together.
Then we can write their own view resolver, ContentNegotiatingViewResolver will automatically be combined. When parsing the view, the view will traverse the parser to parse until it finds a suitable view resolver.


These three are dealing with static resources. Principle, that is, through a static resource mapping.


  • Automatic registration of Converter, GenericConverter, and Formatter beans.

Automatically registered converter, formatter. For example, the date format, encapsulated objects and the like.

@Override
public void addFormatters(FormatterRegistry registry) {
    for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
        registry.addConverter(converter);
    }
    for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
        registry.addConverter(converter);
    }
    for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
        registry.addFormatter(formatter);
    }
}

httpMessage converter. In the original version of the Spring mvc, stress is a viewModel, to view the parser to parse, and now use the converter, the data into json.

A look into this category:

public HttpMessageConverters(boolean addDefaultConverters,
        Collection<HttpMessageConverter<?>> converters) {
    List<HttpMessageConverter<?>> combined = getCombinedConverters(converters,
            addDefaultConverters ? getDefaultConverters() : Collections.emptyList());
    combined = postProcessConverters(combined);
    this.converters = Collections.unmodifiableList(combined);
}

It also put the container to HttpMessageConverter all grouped together, everywhere on this idea, so help us define your own converter.


Error code converter means.


@Override
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
    try {
        return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
    }
    catch (NoSuchBeanDefinitionException ex) {
        return super.getConfigurableWebBindingInitializer();
    }
}

Take from the container, get, call the parent class method. This is the wording that makes Spring Boot can auto-configuration, and support for custom.

public void initBinder(WebDataBinder binder) {
    binder.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
    if (this.directFieldAccess) {
        binder.initDirectFieldAccess();
    }

    if (this.messageCodesResolver != null) {
        binder.setMessageCodesResolver(this.messageCodesResolver);
    }

    if (this.bindingErrorProcessor != null) {
        binder.setBindingErrorProcessor(this.bindingErrorProcessor);
    }

    if (this.validator != null && binder.getTarget() != null && this.validator.supports(binder.getTarget().getClass())) {
        binder.setValidator(this.validator);
    }

    if (this.conversionService != null) {
        binder.setConversionService(this.conversionService);
    }

    if (this.propertyEditorRegistrars != null) {
        PropertyEditorRegistrar[] var2 = this.propertyEditorRegistrars;
        int var3 = var2.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            PropertyEditorRegistrar propertyEditorRegistrar = var2[var4];
            propertyEditorRegistrar.registerCustomEditors(binder);
        }
    }

}

Binder data, the data is transmitted to the front end, conversion, we bound to the control layer parameter setting method.


If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.

Want to use the existing properties, would also like to add some other features, you can customize the configuration WebMvcRegistrationsAdapter class, but to cancel @EnableWebMvc comment.
If added @EnableWebMvc notes, part of Spring Boot automatic configuration becomes ineffective.

  1. @EnableWebMvc the core, introducing a DelegatingWebMvcConfiguration class.
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {

2) This configuration class inherits WebMvcConfigurationSupport

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

3), while Spring Boot automatic configuration to take effect, there is no WebMvcConfigurationSupport this class, so the automatic configuration will not take effect.

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
        TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

4), @ EnableWebMvc WebMvcConfigurationSupport assembly will come introduced;
. 5), only introducing WebMvcConfigurationSupport SpringMVC basic function;

Summary:
1, when the automatic configuration of components, first determines whether there is a corresponding component, if present, the loading does not exist, a default is generated. If a plurality of components allows for example view resolver, then combined together. We can define your own components, Spring Boot help us expand configuration.
2) In SpringBoot there will be a lot of xxxConfigurer help us expand configuration.
3), in SpringBoot there will be lots of xxxCustomizer help us to customize the configuration.

Reproduced in: https: //www.jianshu.com/p/2418f71011c0

Guess you like

Origin blog.csdn.net/weixin_34255055/article/details/91273177