欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談springboot自動(dòng)配置原理

 更新時(shí)間:2019年08月29日 11:05:25   作者:garfieldzf  
這篇文章主要介紹了淺談springboot自動(dòng)配置原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

從main函數(shù)說起

一切的開始要從SpringbootApplication注解說起。

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


@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {
  
}

其中最重要的就是EnableAutoConfiguration注解,開啟自動(dòng)配置。

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

通過Import注解導(dǎo)入AutoConfigurationImportSelector。在這個(gè)類中加載/META-INF/spring.factories文件的信息,然后篩選出以EnableAutoConfiguration為key的數(shù)據(jù),加載到IOC容器中,實(shí)現(xiàn)自動(dòng)配置功能。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

從表面看就是自動(dòng)配置包,主要使用了Import注解,導(dǎo)入了Registrar類。這里Registrar類的registerBeanDefinitions方法導(dǎo)包,也就是導(dǎo)入當(dāng)前main函數(shù)所在路徑的包地址,我這里是com.zhangfei。

怎么自動(dòng)裝配其他N個(gè)類

Import({AutoConfigurationImportSelector.class})該注解給當(dāng)前配置類導(dǎo)入另外N個(gè)自動(dòng)配置類。

這里既然導(dǎo)入N個(gè)自動(dòng)配置類,那么都導(dǎo)入哪些類呢?

//AutoConfigurationImportSelector實(shí)現(xiàn)DeferredImportSelector接口,而DeferredImportSelector接口又繼承了ImportSelector
public interface ImportSelector {
  String[] selectImports(AnnotationMetadata var1);
}

AutoConfigurationImportSelector通過實(shí)現(xiàn)接口ImportSelector的selectImports方法返回需要導(dǎo)入的組件,selectImports方法返回一個(gè)全類名字符串?dāng)?shù)組。

主角上場(chǎng)

//AutoConfigurationImportSelector.java
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
  if (!isEnabled(annotationMetadata)) {
    return NO_IMPORTS;
  }
  AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
  AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata);
  return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {
  if (!isEnabled(annotationMetadata)) {
    return EMPTY_ENTRY;
  }
  AnnotationAttributes attributes = getAttributes(annotationMetadata);
  List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
  configurations = removeDuplicates(configurations);
  Set<String> exclusions = getExclusions(annotationMetadata, attributes);
  checkExcludedClasses(configurations, exclusions);
  configurations.removeAll(exclusions);
  configurations = filter(configurations, autoConfigurationMetadata);
  fireAutoConfigurationImportEvents(configurations, exclusions);
  return new AutoConfigurationEntry(configurations, exclusions);
}

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
  List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
  return configurations;
}

這里又開始調(diào)用SpringFactoriesLoader.loadFactoryNames。
SpringFactoriesLoader.loadFactoryNames方法中關(guān)鍵的三步:
(1)從當(dāng)前項(xiàng)目的類路徑中獲取所有 META-INF/spring.factories 這個(gè)文件下的信息.
(2)將上面獲取到的信息封裝成一個(gè) Map 返回,EnableAutoConfiguration為key。
(3)從返回的Map中通過剛才傳入的 EnableAutoConfiguration.class參數(shù),獲取該 key 下的所有值。

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
  String factoryClassName = factoryClass.getName();
  return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
  MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
  if (result != null) {
    return result;
  } else {
    try {
      Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
      LinkedMultiValueMap result = new LinkedMultiValueMap();

      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 factoryClassName = ((String)entry.getKey()).trim();
          String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
          int var10 = var9.length;

          for(int var11 = 0; var11 < var10; ++var11) {
            String factoryName = var9[var11];
            result.add(factoryClassName, factoryName.trim());
          }
        }
      }

      cache.put(classLoader, result);
      return result;
    } catch (IOException var13) {
      throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
    }
  }
}

自動(dòng)配置都有哪些內(nèi)容呢?

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
...其他省略

XXXAutoConfiguration和XXProperties

在spring.factories文件中看到的都是自動(dòng)配置類,那么自動(dòng)配置用到的屬性值在那里呢?我們拿出redis為例

@Configuration
@ConditionalOnClass(RedisOperations.class) //判斷當(dāng)前項(xiàng)目有沒有這個(gè)類RedisOperations.class
@EnableConfigurationProperties(RedisProperties.class) //啟用配置屬性,這里看到了熟悉的XXXProperties
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) //導(dǎo)入這兩個(gè)類
public class RedisAutoConfiguration {

  @Bean
  @ConditionalOnMissingBean(name = "redisTemplate")
  public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
      throws UnknownHostException {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
  }

  @Bean
  @ConditionalOnMissingBean
  public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
      throws UnknownHostException {
    StringRedisTemplate template = new StringRedisTemplate();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
  }
}

 
//這里則保存redis初始化時(shí)的屬性
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {

  private int database = 0;

  private String url;

  private String host = "localhost";

  private String password;

  private int port = 6379;

  private boolean ssl;

}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入淺出Java中重試機(jī)制的多種方式

    深入淺出Java中重試機(jī)制的多種方式

    重試機(jī)制在分布式系統(tǒng)中,或者調(diào)用外部接口中,都是十分重要的。重試機(jī)制可以保護(hù)系統(tǒng)減少因網(wǎng)絡(luò)波動(dòng)、依賴服務(wù)短暫性不可用帶來的影響,讓系統(tǒng)能更穩(wěn)定的運(yùn)行的一種保護(hù)機(jī)制。本文就來和大家聊聊Java中重試機(jī)制的多種方式
    2023-03-03
  • 淺談利用Spring的AbstractRoutingDataSource解決多數(shù)據(jù)源的問題

    淺談利用Spring的AbstractRoutingDataSource解決多數(shù)據(jù)源的問題

    本篇文章主要介紹了淺談利用Spring的AbstractRoutingDataSource解決多數(shù)據(jù)源的問題,具有一定的參考價(jià)值,有需要的可以了解一下
    2017-08-08
  • Spring定時(shí)任務(wù)無故停止又不報(bào)錯(cuò)的解決

    Spring定時(shí)任務(wù)無故停止又不報(bào)錯(cuò)的解決

    這篇文章主要介紹了Spring定時(shí)任務(wù)無故停止又不報(bào)錯(cuò)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 基于Java多線程notify與notifyall的區(qū)別分析

    基于Java多線程notify與notifyall的區(qū)別分析

    本篇文章對(duì)Java中多線程notify與notifyall的區(qū)別進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • 詳解java中繼承關(guān)系類加載順序問題

    詳解java中繼承關(guān)系類加載順序問題

    這篇文章主要介紹了詳解java中繼承關(guān)系類加載順序問題的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 在SpringBoot中配置MySQL數(shù)據(jù)庫的詳細(xì)指南

    在SpringBoot中配置MySQL數(shù)據(jù)庫的詳細(xì)指南

    在 Spring Boot 中配置數(shù)據(jù)庫是一個(gè)相對(duì)簡(jiǎn)單的過程,通常涉及到以下幾個(gè)步驟:添加數(shù)據(jù)庫驅(qū)動(dòng)依賴、配置數(shù)據(jù)源屬性、以及可選的配置 JPA(如果使用),下面是小編給大家編寫的一個(gè)詳細(xì)的指南,以MySQL 數(shù)據(jù)庫為例,需要的朋友可以參考下
    2024-12-12
  • java中實(shí)體類實(shí)現(xiàn)時(shí)間日期自動(dòng)轉(zhuǎn)換方式

    java中實(shí)體類實(shí)現(xiàn)時(shí)間日期自動(dòng)轉(zhuǎn)換方式

    這篇文章主要介紹了java中實(shí)體類實(shí)現(xiàn)時(shí)間日期自動(dòng)轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • cmd使用javac和java及注意事項(xiàng)

    cmd使用javac和java及注意事項(xiàng)

    這篇文章主要介紹了cmd使用javac和java及注意事項(xiàng),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2021-12-12
  • springboot實(shí)現(xiàn)異步任務(wù)

    springboot實(shí)現(xiàn)異步任務(wù)

    這篇文章主要為大家詳細(xì)介紹了springboot實(shí)現(xiàn)異步任務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Java?Servlet實(shí)現(xiàn)表白墻的代碼實(shí)例

    Java?Servlet實(shí)現(xiàn)表白墻的代碼實(shí)例

    最近用Servlet做了個(gè)小項(xiàng)目,分享給大家,下面這篇文章主要給大家介紹了關(guān)于Java?Servlet實(shí)現(xiàn)表白墻的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02

最新評(píng)論