Spring boot 梳理 -@SpringBootApplication、@EnableAutoConfiguration與(@EnableWebMVC、WebMvcConfigurationSupport,WebMvcConfigurer和WebMvcConfigurationAdapter)


  1. @EnableWebMvc=繼承DelegatingWebMvcConfiguration=繼承WebMvcConfigurationSupport
    1. 直接看源碼,@EnableWebMvc實際上引入一個DelegatingWebMvcConfiguration  
      1. @Retention(RetentionPolicy.RUNTIME)
        @Target({ElementType.TYPE})
        @Documented
        @Import({DelegatingWebMvcConfiguration.class})
        public @interface EnableWebMvc {
        }

         

      2. DelegatingWebMvcConfiguration繼承了WebMvcConfigurationSupport
        1. @Configuration
          public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
          ...
    2. @EnableWebMvc,WebMvcConfigurationSupport,WebMvcConfigurer和WebMvcConfigurationAdapter使用

      1. Java8給出了新的特性,使得接口方法可以擁有默認實現。所以你現在可以直接實現WebMvcConfigurer而不用像以前那樣通過繼承它的實現類來達到目的。
      2. WebMvcConfigurationAdapter已經廢棄,最好用implements WebMvcConfigurer代替

        @Configuration
        public class MyConfig implements WebMvcConfigurer {
            
        }

        如果使用繼承,WebMvcConfigurationSupport,DelegatingWebMvcConfiguration,或者使用@EnableWebMvc,

        需要注意會覆蓋application.properties中關於WebMvcAutoConfiguration的設置,需要在自定義配置中實現,如

        springboot2.0、spring5.0 攔截器配置WebMvcConfigurerAdapter過時使用WebMvcConfigurationSupport來代替 新坑

        示例如下

        Configuration
        @EnableWebMvc
        public class MyConfig implements WebMvcConfigurer {
        
        }
        @Configuration
        public class MyConfig extends WebMvcConfigurationSupport {
        
        }
        @Configuration
        public class MyConfig extends DelegatingWebMvcConfiguration {
        
        }
        上面代碼中需要在類中實現關於WebMvcAutoConfiguration的配置,而不是在application.properties中。
      3. 總結

        implements WebMvcConfigurer : 不會覆蓋@EnableAutoConfiguration關於WebMvcAutoConfiguration的配置
        @EnableWebMvc + implements WebMvcConfigurer : 會覆蓋@EnableAutoConfiguration關於WebMvcAutoConfiguration的配置
        extends WebMvcConfigurationSupport :會覆蓋@EnableAutoConfiguration關於WebMvcAutoConfiguration的配置
        extends DelegatingWebMvcConfiguration :會覆蓋@EnableAutoConfiguration關於WebMvcAutoConfiguration的配置
        只要使用@EnableWebMvc(隱式使用WebMvcConfigurationSupport)或顯示使用WebMvcConfigurationSupport
        
        就會屏蔽springboot的@EnableAutoConfiguration中的設置

         

         
        @EnableWebMvc=WebMvcConfigurationSupport,使用了@EnableWebMvc注解等於擴展了WebMvcConfigurationSupport但是沒有重寫任何方法
        @EnableWebMvc+extends WebMvcConfigurationAdapter,在擴展的類中重寫父類的方法即可,這種方式會屏蔽springboot的@EnableAutoConfiguration中的設置
        extends WebMvcConfigurationSupport,在擴展的類中重寫父類的方法即可,這種方式會屏蔽springboot的@EnableAutoConfiguration中的設置
        extends WebMvcConfigurationAdapter,在擴展的類中重寫父類的方法即可,這種方式依舊使用springboot的@EnableAutoConfiguration中的設置

      4. 總結:大家在使用2.0版本的springboot的時候 使用WebMvcConfigurationSupport類配置攔截器時一定要重寫addResourceHandlers來實現靜態資源的映射,不要使用application.properties中添加配置來實現映射,不然資源會映射不成功導致打開頁面資源一直加載不到。會出現下面這種奇怪的問題
      5. 擴展SpringMVC:編寫一個配置類(@Configuration),是WebMvcConfigurerAdapter類型;不能標注@EnableWebMvc;

        1.   
          @Configuration
          // WebMvcConfigurerAdapter過時,使用WebMvcConfigurer接口
          public class MyMvcConfig implements WebMvcConfigurer {
              @Override
              public void addViewControllers(ViewControllerRegistry registry) {
                  // 瀏覽器發送 /cuzz 請求來到 success
                  registry.addViewController("/cuzz").setViewName("success");
              }
          }

           

      6. 半全面接管SpringMVC:SpringBoot對SpringMVC的自動配置不需要了,所有都是我們自己配置;所有的SpringMVC的自動配置都失效了,我們需要在配置類中添加@EnableWebMvc即可;

        1.   在WebMvcConfigurationSupport(@EnableWebMvc)和@EnableAutoConfiguration這兩種方式都有一些默認的設定 
          而WebMvcConfigurationAdapter則是一個abstract class
        2. //使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能
          @EnableWebMvc
          @Configuration
          public class MyMvcConfig extends WebMvcConfigurerAdapter {
          
              @Override
              public void addViewControllers(ViewControllerRegistry registry) {
                 // super.addViewControllers(registry);
                  //瀏覽器發送 /atguigu 請求來到 success
                  registry.addViewController("/atguigu").setViewName("success");
              }
          }

           

  2.   @EnableAutoConfiguration
    1. 導入jar下面的配置文件META-INF/spring.factories
    2. @EnableAutoConfiguration是springboot項目的啟動類注解@SpringBootApplication的子元素,主要功能為自動配置
    3. @EnableAutoConfiguration實際是導入了EnableAutoConfigurationImportSelector和Registrar兩個類
    4. @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @AutoConfigurationPackage
      @Import({AutoConfigurationImportSelector.class})
      public @interface EnableAutoConfiguration {
      ...
      }
      @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @Import({Registrar.class})
      public @interface AutoConfigurationPackage {
      }

       

    5. 這兩個類的具體原理有些復雜,不太清除,主要內容是通過SpringFactoriesLoader.loadFactoryNames()導入jar下面的配置文件META-INF/spring.factories
      1. 在AutoConfigurationImportSelector類中可以看到通過 SpringFactoriesLoader.loadFactoryNames()
        把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一個xxxAutoConfiguration文件都加載到容器中,spring.factories文件里每一個xxxAutoConfiguration文件一般都會有下面的條件注解:
        
            @ConditionalOnClass : classpath中存在該類時起效
            @ConditionalOnMissingClass : classpath中不存在該類時起效
            @ConditionalOnBean : DI容器中存在該類型Bean時起效
            @ConditionalOnMissingBean : DI容器中不存在該類型Bean時起效
            @ConditionalOnSingleCandidate : DI容器中該類型Bean只有一個或@Primary的只有一個時起效

         

      2. SpringFactoriesLoader屬於Spring框架私有的一種擴展方案(類似於Java的SPI方案java.util.ServiceLoader),其主要功能就是從指定的配置文件META-INF/spring-factories加載配置,spring-factories是一個典型的java properties文件,只不過Key和Value都是Java類型的完整類名,比如:

         

    6. 配置文件中的內容如下
      1. # Auto Configure
        org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
        org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
        ...
        org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\

         

    7.   其中有WebMvcAutoConfiguration,WebMvcAutoConfiguration源碼如下
      1. @Configuration
        @ConditionalOnWebApplication(
            type = Type.SERVLET
        )
        @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
        @ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
        @AutoConfigureOrder(-2147483638)
        @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})
        public class WebMvcAutoConfiguration {
        ...猜測,Spring boot 在此處加載 application.properties 中關於MVC的默認配置;如果@Conditional返回false,則該配置類不執行
        }

         

      2. @ConditionalOnMissingBean({WebMvcConfigurationSupport.class})意思是如果存在它修飾的類的bean
        ,則不需要再創建這個bean。
      3. 由此可得出結論:
        如果有配置文件繼承了DelegatingWebMvcConfiguration,
        或者WebMvcConfigurationSupport,或者配置文件有@EnableWebMvc,那么 @EnableAutoConfiguration 中的
        WebMvcAutoConfiguration 將不會被自動配置,而是使用WebMvcConfigurationSupport的配置。
  3. @SpringBootApplication
    1. @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @SpringBootConfiguration
      @EnableAutoConfiguration
      @ComponentScan(
          excludeFilters = {@Filter(
          type = FilterType.CUSTOM,
          classes = {TypeExcludeFilter.class}
      ), @Filter(
          type = FilterType.CUSTOM,
          classes = {AutoConfigurationExcludeFilter.class}
      )}
      )
      public @interface SpringBootApplication {
      ...
      }

       

  4. 轉:https://www.cnblogs.com/sufferingStriver/p/9026764.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM