91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中SpringBoot自動裝配的原理是什么

發布時間:2022-02-24 18:37:00 來源:億速云 閱讀:158 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“Java中SpringBoot自動裝配的原理是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Java中SpringBoot自動裝配的原理是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

    運行原理

    為了研究,我們正常從父項目的pom.xml開始進行研究。

    pom.xml

    父依賴 spring-boot-starter-parent主要用來管理項目的資源過濾和插件

    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.2.5.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
    </parent>

    點父依賴進去查看,發現還有一個父依賴spring-boot-dependencies,這里的這個父依賴才是真正管理springboot應用里面的所有依賴版本的地方,是springboot的版本控制中心。

    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.2.5.RELEASE</version>
      <relativePath>../../spring-boot-dependencies</relativePath>
    </parent>

    啟動器:spring-boot-starter-xxx:springboot的場景啟動器

    spring-boot-starter-web:導入web依賴的組件

    <dependency>    <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    主程序

    @SpringBootApplication

    作用:標注這是一個springboot主程序類,說明這是一個springboot應用,springboot就是運行這個類的mian方法啟動的springboot應用。

    @SpringBootApplication //標注這是一個主程序類,說明這是一個springboot應用
    public class Springboot01HelloworldApplication {
    
      public static void main(String[] args) {
        //這里啟動了一個服務,而不是執行了一個方法。
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
      }
    }

    點@SpringBootApplication繼續研究,會發現有@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan這三個注解

    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(
      excludeFilters = {@Filter(
      type = FilterType.CUSTOM,
      classes = {TypeExcludeFilter.class}
    ), @Filter(
      type = FilterType.CUSTOM,
      classes = {AutoConfigurationExcludeFilter.class}
    )}
    )

    1.@ComponentScan: spring自動掃描包

    這個我們在spring配置文件中見到過,它用來自動掃描并加載符合條件的組件或者bean,并將bean加載到IOC容器中。

    2.@SpringBootConfiguration: springboot的配置類

    標注在某個類上,說明這個類是springboot的配置類,在這里它就說明SpringBootApplication這個類是springboot的配置類。

    我們繼續點@SpringBootConfiguration進去查看,會發現 @Configuration這個注解

    2.1 @Configuration:配置類,用來配置spring的xml文件

    我們繼續點@Configuration進去查看,會發現 @Component這個注解。

    2.2 @Component:組件,說明啟動類本身也是一個組件,負責啟動應用。

    至此,@SpringBootConfiguration這條線,我們研究完了。

    3.@EnableAutoConfiguration:開啟自動裝配,通過@EnableAutoConfiguration來幫我們自動配置之前我們需要配置的東西。
    我們繼續點@EnableAutoConfiguration進去查看,會發現 @AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class}) 這兩個注解。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
      String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
      Class<?>[] exclude() default {};
    
      String[] excludeName() default {};
    }

    3.1 @AutoConfigurationPackage自動裝配包

    繼續點進去查看,出現@Import({Registrar.class})這個注解

    3.1.1 @Import({Registrar.class}): spring底層注解,給容器導入一個組件

    Registrar.class: 將主啟動類所在包及所在包下面的所有子包里面所有的組件都掃描到Spring容器。

    至此,@AutoConfigurationPackage這條線我們也研究完了。

    3.2 @Import({AutoConfigurationImportSelector.class}): 給容器導入組件

    AutoConfigurationImportSelector.class:自動裝配導入選擇器。

    導入的選擇器分析:

    1.我們點進去AutoConfigurationImportSelector.class這個類的源碼進行探究,

    2.我們點擊getCandidateConfigurations進一步分析

      protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
      }

    2.1 使用了getSpringFactoriesLoaderFactoryClass()方法,返回一開始我們看到的啟動自動配置文件的注解類EnableAutoConfiguration.class

      protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
      }

    2.2 發現它調用了SpringFactoriesLoader類的靜態方法,我們點擊loadFactoryNames進入loadFactoryNames()

    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
          classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }
    
        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
      }

    發現它又調用了loadSpringFactories()方法,點進去查看

     private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = (Map)cache.get(classLoader);
        if (result != null) {
          return result;
        } else {
          HashMap result = new HashMap();
    
          try {
            Enumeration urls = classLoader.getResources("META-INF/spring.factories");
    
            while(urls.hasMoreElements()) {
              URL url = (URL)urls.nextElement();
              UrlResource resource = new UrlResource(url);
              Properties properties = PropertiesLoaderUtils.loadProperties(resource);
              Iterator var6 = properties.entrySet().iterator();
    
              while(var6.hasNext()) {
                Entry<?, ?> entry = (Entry)var6.next();
                String factoryTypeName = ((String)entry.getKey()).trim();
                String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                String[] var10 = factoryImplementationNames;
                int var11 = factoryImplementationNames.length;
    
                for(int var12 = 0; var12 < var11; ++var12) {
                  String factoryImplementationName = var10[var12];
                  ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
                    return new ArrayList();
                  })).add(factoryImplementationName.trim());
                }
              }
            }
    
            result.replaceAll((factoryType, implementations) -> {
              return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
            });
            cache.put(classLoader, result);
            return result;
          } catch (IOException var14) {
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
          }
        }
      }

    源碼分析:

    1. MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);獲得classLoader,我們返回可以看到這里得到的就是EnableAutoConfiguration標注的類本身

    2. Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");獲取一個資源 "META-INF/spring.factories"

    3. while循環,讀取到的資源遍歷,封裝成為一個Properties

    spring.factories文件

    我們在上面的自動配置類隨便找一個打開看看,比如 :WebMvcAutoConfiguration

    都是大家熟悉的配置,所以,自動配置真正實現是從classpath中搜尋所有的META-INF/spring.factories配置文件 ,并將其中對應的 org.springframework.boot.autoconfigure. 包下的配置項,通過反射實例化為對應標注了 @Configuration的JavaConfig形式的IOC容器配置類 , 然后將這些都匯總成為一個實例并加載到IOC容器中。

    總結

    1. SpringBoot在啟動的時候從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的值

    2. 將這些值作為自動配置類導入容器,自動配置類就生效,幫我們進行自動配置工作;

    3. 整個J2EE的整體解決方案和自動配置都在springboot-autoconfigure的jar包中;

    4. 它會給容器中導入非常多的自動配置類 (xxxAutoConfiguration), 就是給容器中導入這個場景需要的所有組件 , 并配置好這些組件 ;

    5. 有了自動配置類 , 免去了我們手動編寫配置注入功能組件等的工作;

    主啟動類

    SpringApplication

    @SpringBootApplication
    public class SpringbootApplication {
      public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args);
      }
    }

    分析:

    1. SpringbootApplication.class:應用參數的入口

    2. args:命令行參數

    3. 該方法返回的是一個ConfigurableApplicationContext對象

    SpringApplication主要做的事情:

    1. 推斷應用的類型是普通的項目還是Web項目

    2. 查找并加載所有可用初始化器 , 設置到initializers屬性中

    3. 找出所有的應用程序監聽器,設置到listeners屬性中

    4. 推斷并設置main方法的定義類,找到運行的主類

    讀到這里,這篇“Java中SpringBoot自動裝配的原理是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    常宁市| 中江县| 平顺县| 张家港市| 湟中县| 浦县| 班玛县| 罗山县| 祁东县| 桂平市| 大冶市| 邵阳县| 昭苏县| 德江县| 梁平县| 清流县| 隆尧县| 六枝特区| 甘洛县| 浪卡子县| 湟中县| 湘潭市| 堆龙德庆县| 高唐县| 南京市| 团风县| 玉屏| 唐海县| 巴林左旗| 元氏县| 太白县| 桂林市| 弥勒县| 浮山县| 景谷| 贡山| 北海市| 黔西县| 东兰县| 乐东| 长垣县|