最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談springboot自動配置原理

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

從main函數(shù)說起

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

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


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

其中最重要的就是EnableAutoConfiguration注解,開啟自動配置。

@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注解導入AutoConfigurationImportSelector。在這個類中加載/META-INF/spring.factories文件的信息,然后篩選出以EnableAutoConfiguration為key的數(shù)據(jù),加載到IOC容器中,實現(xiàn)自動配置功能。

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

}

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

怎么自動裝配其他N個類

Import({AutoConfigurationImportSelector.class})該注解給當前配置類導入另外N個自動配置類。

這里既然導入N個自動配置類,那么都導入哪些類呢?

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

AutoConfigurationImportSelector通過實現(xiàn)接口ImportSelector的selectImports方法返回需要導入的組件,selectImports方法返回一個全類名字符串數(shù)組。

主角上場

//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方法中關鍵的三步:
(1)從當前項目的類路徑中獲取所有 META-INF/spring.factories 這個文件下的信息.
(2)將上面獲取到的信息封裝成一個 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);
    }
  }
}

自動配置都有哪些內(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文件中看到的都是自動配置類,那么自動配置用到的屬性值在那里呢?我們拿出redis為例

@Configuration
@ConditionalOnClass(RedisOperations.class) //判斷當前項目有沒有這個類RedisOperations.class
@EnableConfigurationProperties(RedisProperties.class) //啟用配置屬性,這里看到了熟悉的XXXProperties
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) //導入這兩個類
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初始化時的屬性
@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;

}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • 基于Feign實現(xiàn)異步調(diào)用

    基于Feign實現(xiàn)異步調(diào)用

    近期,需要對之前的接口進行優(yōu)化,縮短接口的響應時間,但是springcloud中的feign是不支持傳遞異步化的回調(diào)結果的,因此有了以下的解決方案,記錄一下,需要的朋友可以參考下
    2021-05-05
  • Java資源緩存 之 LruCache

    Java資源緩存 之 LruCache

    LruCache (此類在android-support-v4的包中提供) 這個類非常適合用來緩存圖片,它的主要算法原理是把最近使用的對象用強引用存儲在 LinkedHashMap 中,并且把最近最少使用的對象在緩存值達到預設定值之前從內(nèi)存中移除。
    2016-08-08
  • RabbitMQ的Direct Exchange模式實現(xiàn)的消息發(fā)布案例(示例代碼)

    RabbitMQ的Direct Exchange模式實現(xiàn)的消息發(fā)布案例(示例代碼)

    本文介紹了RabbitMQ的DirectExchange模式下的消息發(fā)布和消費的實現(xiàn),詳細說明了如何在DirectExchange模式中進行消息的發(fā)送和接收,以及消息處理的基本方法,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題

    SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題

    這篇文章主要介紹了SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 使用BufferedReader讀取本地文件的操作

    使用BufferedReader讀取本地文件的操作

    這篇文章主要介紹了使用BufferedReader讀取本地文件的操作,具有很好的參考價值,希望對大家有所幫助。
    2021-07-07
  • 使用Spring Boot的LoggersEndpoint管理日志級別

    使用Spring Boot的LoggersEndpoint管理日志級別

    這篇文章主要為大家介紹了使用Spring Boot的LoggersEndpoint管理日志級別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Java中的super關鍵字_動力節(jié)點Java學院整理

    Java中的super關鍵字_動力節(jié)點Java學院整理

    這篇文章主要介紹了Java中的super關鍵字的相關知識,需要的朋友參考下
    2017-04-04
  • idea在運行期間,實現(xiàn)讓修改的頁面實時生效

    idea在運行期間,實現(xiàn)讓修改的頁面實時生效

    這篇文章主要介紹了idea在運行期間,實現(xiàn)讓修改的頁面實時生效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 基于LinkedHashMap實現(xiàn)LRU緩存

    基于LinkedHashMap實現(xiàn)LRU緩存

    LinkedHashMap是Java集合中一個常用的容器,它繼承了HashMap, 是一個有序的Hash表。那么該如何基于LinkedHashMap實現(xiàn)一個LRU緩存呢?本文將介紹LinkedHashMap的實現(xiàn)原理,感興趣的同學可以參考一下
    2023-05-05
  • Java中使用fastjson設置字段不序列化

    Java中使用fastjson設置字段不序列化

    這篇文章主要介紹了Java中使用fastjson設置字段不序列化,alibaba的fasetjson可以設置字段不序列化,使用@JSONField注解的serialize屬性,該屬性默認是可以序列化的,設置成false就表示不可序列化,需要的朋友可以參考下
    2023-12-12

最新評論

彩票| 三明市| 万全县| 甘孜县| 康乐县| 博白县| 东山县| 诏安县| 确山县| 宝坻区| 台前县| 无极县| 福州市| 平遥县| 加查县| 巴彦县| 三亚市| 泽州县| 金华市| 桑日县| 青铜峡市| 松潘县| 滦平县| 宿州市| 咸阳市| 瓦房店市| 莆田市| 郓城县| 临高县| 五华县| 鹰潭市| 开封市| 庐江县| 凌源市| 佛教| 堆龙德庆县| 仙桃市| 河东区| 天柱县| 沙河市| 白玉县|