亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

SpringBoot@EnableAutoConfiguration的使用方法

發布時間:2021-09-14 23:38:56 來源:億速云 閱讀:174 作者:chen 欄目:編程語言

本篇內容主要講解“SpringBoot@EnableAutoConfiguration的使用方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“SpringBoot@EnableAutoConfiguration的使用方法”吧!

使用姿勢

講原理前先說下使用姿勢。

在project A中定義一個bean。

package com.wangzhi;import org.springframework.stereotype.Service;@Servicepublic class Dog {}

并在該project的resources/META-INF/下創建一個叫spring.factories的文件,該文件內容如下

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wangzhi.Dog

然后在project B中引用project A的jar包。

projectA代碼如下:

package com.wangzhi.springbootdemo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.ComponentScan;@EnableAutoConfigurationpublic class SpringBootDemoApplication {  public static void main(String[] args) {    ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoApplication.class, args);    System.out.println(context.getBean(com.wangzhi.Dog.class));  }}

打印結果:

com.wangzhi.Dog@3148f668

原理解析

總體分為兩個部分:一是收集所有spring.factories中EnableAutoConfiguration相關bean的類,二是將得到的類注冊到spring容器中。

收集bean定義類

在spring容器啟動時,會調用到AutoConfigurationImportSelector#getAutoConfigurationEntry

protected AutoConfigurationEntry getAutoConfigurationEntry(    AutoConfigurationMetadata autoConfigurationMetadata,    AnnotationMetadata annotationMetadata) {  if (!isEnabled(annotationMetadata)) {    return EMPTY_ENTRY;  }  // EnableAutoConfiguration注解的屬性:exclude,excludeName等  AnnotationAttributes attributes = getAttributes(annotationMetadata);  // 得到所有的Configurations  List<String> configurations = getCandidateConfigurations(annotationMetadata,      attributes);  // 去重  configurations = removeDuplicates(configurations);  // 刪除掉exclude中指定的類  Set<String> exclusions = getExclusions(annotationMetadata, attributes);  checkExcludedClasses(configurations, exclusions);  configurations.removeAll(exclusions);  configurations = filter(configurations, autoConfigurationMetadata);  fireAutoConfigurationImportEvents(configurations, exclusions);  return new AutoConfigurationEntry(configurations, exclusions);}

getCandidateConfigurations會調用到方法loadFactoryNames:

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {    // factoryClassName為org.springframework.boot.autoconfigure.EnableAutoConfiguration String factoryClassName = factoryClass.getName();    // 該方法返回的是所有spring.factories文件中key為org.springframework.boot.autoconfigure.EnableAutoConfiguration的類路徑 return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = cache.get(classLoader); if (result != null) {  return result; } try {      // 找到所有的"META-INF/spring.factories"  Enumeration<URL> urls = (classLoader != null ?   classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :   ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));  result = new LinkedMultiValueMap<>();  while (urls.hasMoreElements()) {  URL url = urls.nextElement();  UrlResource resource = new UrlResource(url);        // 讀取文件內容,properties類似于HashMap,包含了屬性的key和value  Properties properties = PropertiesLoaderUtils.loadProperties(resource);  for (Map.Entry<?, ?> entry : properties.entrySet()) {   String factoryClassName = ((String) entry.getKey()).trim();          // 屬性文件中可以用','分割多個value   for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {   result.add(factoryClassName, factoryName.trim());   }  }  }  cache.put(classLoader, result);  return result; } catch (IOException ex) {  throw new IllegalArgumentException("Unable to load factories from location [" +   FACTORIES_RESOURCE_LOCATION + "]", ex); } }

注冊到容器

在上面的流程中得到了所有在spring.factories中指定的bean的類路徑,在processGroupImports方法中會以處理@import注解一樣的邏輯將其導入進容器。

public void processGroupImports() {  for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {    // getImports即上面得到的所有類路徑的封裝    grouping.getImports().forEach(entry -> {      ConfigurationClass configurationClass = this.configurationClasses.get(          entry.getMetadata());      try {        // 和處理@Import注解一樣        processImports(configurationClass, asSourceClass(configurationClass),            asSourceClasses(entry.getImportClassName()), false);      }      catch (BeanDefinitionStoreException ex) {        throw ex;      }      catch (Throwable ex) {        throw new BeanDefinitionStoreException(            "Failed to process import candidates for configuration class [" +                configurationClass.getMetadata().getClassName() + "]", ex);      }    });  }}private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,  Collection<SourceClass> importCandidates, boolean checkForCircularImports) { ...  // 遍歷收集到的類路徑  for (SourceClass candidate : importCandidates) {    ...    //如果candidate是ImportSelector或ImportBeanDefinitionRegistrar類型其處理邏輯會不一樣,這里不關注   // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->   // process it as an @Configuration class   this.importStack.registerImport(    currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); // 當作 @Configuration 處理      processConfigurationClass(candidate.asConfigClass(configClass));  ...}        ...}

可以看到,在第一步收集的bean類定義,最終會被以Configuration一樣的處理方式注冊到容器中。

End

@EnableAutoConfiguration注解簡化了導入了二方包bean的成本。提供一個二方包給其他應用使用,只需要在二方包里將對外暴露的bean定義在spring.factories中就好了。對于不需要的bean,可以在使用方用@EnableAutoConfiguration的exclude屬性進行排除。

到此,相信大家對“SpringBoot@EnableAutoConfiguration的使用方法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

AI

汝州市| 淄博市| 紫阳县| 宁都县| 章丘市| 东乡| 博客| 沙田区| 浠水县| 凤城市| 正宁县| 隆昌县| 德庆县| 广河县| 曲周县| 汝城县| 望奎县| 阳春市| 曲水县| 临猗县| 旺苍县| 昭通市| 安新县| 扬中市| 靖宇县| 惠来县| 信阳市| 灵寿县| 广丰县| 崇州市| 清河县| 六盘水市| 祁东县| 绥江县| 莱西市| 通许县| 土默特左旗| 麻阳| 黄大仙区| 平舆县| 芮城县|