SpringBoot默认配置原理:以WebMvcAutoConfiguration为例

默认配置类

@EnableAutoConfiguration会开启SpringBoot的自动配置,并且根据你引入的依赖来生效对应的默认配置。那么,这些默认配置是在哪里定义的呢?为何依赖引入就会触发配置呢?

其实,在我们的项目中已经引入了一个依赖:spring-boot-autoconfigure,其中定义了大量自动配置类:下面截图没截完

SpringBoot默认配置原理:以WebMvcAutoConfiguration为例_第1张图片

我们来看一个我们熟悉的,例如SpringMVC,查看mvc的自动配置类:

SpringBoot默认配置原理:以WebMvcAutoConfiguration为例_第2张图片

WebMvcAutoConfiguration源码

SpringBoot默认配置原理:以WebMvcAutoConfiguration为例_第3张图片

上面的注解中:

@ConditionalOnWebApplication(type = Type.SERVLET) 
  ConditionalOn,就是在某个条件下,此处就是满足项目的类是Type.SERVLET类型,也就是一个普通web工程
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
  这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了tomcat依赖自然会有,后两个需要引入SpringMVC才会有。这里就是判断你是否引入了相关依赖,引入依赖后该条件成立,当前类的配置才会生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
  OnMissingBean是说环境中没有指定的Bean才生效

接着,我们查看该类中定义了什么:

WebMvcAutoConfiguration的静态内部类WebMvcAutoConfigurationAdapter中

  视图解析器:

        @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(2147483637);
            return resolver;
        }

上面点击getPrefix,会进入到WebMvcProperties的内部类View

    public static class View {
        private String prefix;
        private String suffix;

        public View() {
        }

        public String getPrefix() {
            return this.prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }

        public String getSuffix() {
            return this.suffix;
        }

        public void setSuffix(String suffix) {
            this.suffix = suffix;
        }
    }

WebMvcAutoConfiguration的静态内部类EnableWebMvcConfiguration中

  处理器适配器(HandlerAdapter): 

        @Bean
        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;
        }

        protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
            if (this.mvcRegistrations != null) {
                RequestMappingHandlerAdapter adapter = this.mvcRegistrations.getRequestMappingHandlerAdapter();
                if (adapter != null) {
                    return adapter;
                }
            }

            return super.createRequestMappingHandlerAdapter();
        }

默认配置属性

这些默认配置的属性来自哪里呢?

内部类WebMvcAutoConfigurationAdapter上的注解

SpringBoot默认配置原理:以WebMvcAutoConfiguration为例_第4张图片

我们看到,这里通过@EnableAutoConfiguration注解引入了3个属性:WebMvcProperties、ResourceProperties、WebProperties

WebMvcProperties的内部类View,找到了内部资源视图解析器的prefix和suffix属性

    public static class View {
        private String prefix;
        private String suffix;

        public View() {
        }

        public String getPrefix() {
            return this.prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }

        public String getSuffix() {
            return this.suffix;
        }

        public void setSuffix(String suffix) {
            this.suffix = suffix;
        }
    }

WebProperties的内部类Resources中,主要定义了静态资源(.js,.html,.css等)的默认查找路径:

    public static class Resources {
        private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
        private String[] staticLocations;
        private boolean addMappings;
        private boolean customized;
        private final WebProperties.Resources.Chain chain;
        private final WebProperties.Resources.Cache cache;

如果我们要覆盖这些默认属性,只需要在application.properties中定义与其前缀prefix和字段名一致的属性即可。 

如果我们不想配置,只需要引入依赖即可,而依赖版本我们也不用操心,因为只要引入了SpringBoot提供的starter,就会自动管理依赖及版本了。

【bak】

原文已更新:https://www.cnblogs.com/uncleyong/p/17103602.html

你可能感兴趣的:(spring,boot,servlet,java,spring,后端)