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

Springboot @Import 詳解

 更新時(shí)間:2018年11月26日 14:17:16   作者:愛(ài)笑的咖啡  
這篇文章主要介紹了Springboot @Import 詳解,仔細(xì)看了下Springboot關(guān)于@Import的處理過(guò)程,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

SpringBoot 的 @Import 用于將指定的類實(shí)例注入之Spring IOC Container中。 

今天抽空在仔細(xì)看了下Springboot 關(guān)于 @Import 的處理過(guò)程, 記下來(lái)以后看。

1. @Import

先看Spring對(duì)它的注釋 (文檔貼過(guò)來(lái)的), 總結(jié)下來(lái)作用就是和xml配置的 <import />標(biāo)簽作用一樣,允許通過(guò)它引入 @Configuration 注解的類 (java config), 引入ImportSelector接口(這個(gè)比較重要, 因?yàn)橐ㄟ^(guò)它去判定要引入哪些@Configuration) 和 ImportBeanDefinitionRegistrar 接口的實(shí)現(xiàn), 也包括 @Component注解的普通類。

但是如果要引入另一個(gè)xml 文件形式配置的 bean, 則需要通過(guò) @ImportResource 注解。

/**
 * Indicates one or more {@link Configuration @Configuration} classes to import.
 *
 * <p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.
 * Allows for importing {@code @Configuration} classes, {@link ImportSelector} and
 * {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component
 * classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).
 *
 * <p>{@code @Bean} definitions declared in imported {@code @Configuration} classes should be
 * accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
 * injection. Either the bean itself can be autowired, or the configuration class instance
 * declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly
 * navigation between {@code @Configuration} class methods.
 *
 * <p>May be declared at the class level or as a meta-annotation.
 *
 * <p>If XML or other non-{@code @Configuration} bean definition resources need to be
 * imported, use the {@link ImportResource @ImportResource} annotation instead.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.0
 * @see Configuration
 * @see ImportSelector
 * @see ImportResource
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

  /**
   * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
   * or regular component classes to import.
   */
  Class<?>[] value();

}

2. ImportSelector

因?yàn)?@Import 的實(shí)現(xiàn)有很多時(shí)候需要借助 ImportSelector 接口, 所以我們?cè)倏聪逻@個(gè)接口的描述, 總結(jié)下來(lái)就是需要通過(guò)這個(gè)接口的實(shí)現(xiàn)去決定要引入哪些 @Configuration。 它如果實(shí)現(xiàn)了以下四個(gè)Aware 接口, 那么spring保證會(huì)在調(diào)用它之前先調(diào)用Aware接口的方法。

至于為什么要保證調(diào)用Aware, 我個(gè)人覺(jué)得應(yīng)該是你可以通過(guò)這些Aware去感知系統(tǒng)里邊所有的環(huán)境變量, 從而決定你具體的選擇邏輯。

/**
 * Interface to be implemented by types that determine which @{@link Configuration}
 * class(es) should be imported based on a given selection criteria, usually one or more
 * annotation attributes.
 *
 * <p>An {@link ImportSelector} may implement any of the following
 * {@link org.springframework.beans.factory.Aware Aware} interfaces, and their respective
 * methods will be called prior to {@link #selectImports}:
 * <ul>
 * <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
 * <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}</li>
 * <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}</li>
 * <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}</li>
 * </ul>
 *
 * <p>ImportSelectors are usually processed in the same way as regular {@code @Import}
 * annotations, however, it is also possible to defer selection of imports until all
 * {@code @Configuration} classes have been processed (see {@link DeferredImportSelector}
 * for details).
 *
 * @author Chris Beams
 * @since 3.1
 * @see DeferredImportSelector
 * @see Import
 * @see ImportBeanDefinitionRegistrar
 * @see Configuration
 */
public interface ImportSelector {

  /**
   * Select and return the names of which class(es) should be imported based on
   * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
   */
  String[] selectImports(AnnotationMetadata importingClassMetadata);

}

3. Springboot 對(duì)@Import注解的處理過(guò)程

Springboot對(duì)注解的處理都發(fā)生在AbstractApplicationContext -> refresh() -> invokeBeanFactoryPostProcessors(beanFactory) -> ConfigurationClassPostProcessor -> postProcessBeanDefinitionRegistry()方法中。

(稍微說(shuō)下也免得我自己忘了, springboot初始化的普通context(非web) 是AnnotationConfigApplicationContext, 在初始化的時(shí)候會(huì)初始化兩個(gè)工具類, AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 分別用來(lái)從 annotation driven 的配置和xml的配置中讀取beanDefinition并向context注冊(cè), 那么在初始化 AnnotatedBeanDefinitionReader 的時(shí)候, 會(huì)向BeanFactory注冊(cè)一個(gè)ConfigurationClassPostProcessor 用來(lái)處理所有的基于annotation的bean, 這個(gè)ConfigurationClassPostProcessor 是 BeanFactoryPostProcessor 的一個(gè)實(shí)現(xiàn),springboot會(huì)保證在  invokeBeanFactoryPostProcessors(beanFactory) 方法中調(diào)用注冊(cè)到它上邊的所有的BeanFactoryPostProcessor)

如下代碼顯示是通過(guò) ConfigurationClassParser 類來(lái)轉(zhuǎn)換的

// Parse each @Configuration class
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

那么在 ConfigurationClassParser -> processConfigurationClass() -> doProcessConfigurationClass() 方法中我們找到了 (這里邊的流程還是很清楚的, 分別按次序處理了@PropertySource, @ComponentScan, @Import, @ImportResource, 在處理這些注解的時(shí)候是通過(guò)遞歸處理來(lái)保證所有的都被處理了)

// Process any @Import annotations
    processImports(configClass, sourceClass, getImports(sourceClass), true);

那接下來(lái)就看它到底是怎么做的 . 流程依然清晰 :

  首先, 判斷如果被import的是 ImportSelector.class 接口的實(shí)現(xiàn), 那么初始化這個(gè)被Import的類, 然后調(diào)用它的selectImports方法去獲得所需要的引入的configuration, 然后遞歸處理

  其次, 判斷如果被import的是 ImportBeanDefinitionRegistrar 接口的實(shí)現(xiàn), 那么初始化后將對(duì)當(dāng)前對(duì)象的處理委托給這個(gè)ImportBeanDefinitionRegistrar (不是特別明白, 只是我的猜測(cè))

  最后, 將import引入的類作為一個(gè)正常的類來(lái)處理 ( 調(diào)用最外層的doProcessConfigurationClass())

所以, 從這里我們知道, 如果你引入的是一個(gè)正常的component, 那么會(huì)作為@Compoent或者@Configuration來(lái)處理, 這樣在BeanFactory里邊可以通過(guò)getBean拿到, 但如果你是 ImportSelector 或者 ImportBeanDefinitionRegistrar 接口的實(shí)現(xiàn), 那么spring并不會(huì)將他們注冊(cè)到beanFactory中,而只是調(diào)用他們的方法。

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
      Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

    if (importCandidates.isEmpty()) {
      return;
    }

    if (checkForCircularImports && isChainedImportOnStack(configClass)) {
      this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
    }
    else {
      this.importStack.push(configClass);
      try {
        for (SourceClass candidate : importCandidates) {
          if (candidate.isAssignable(ImportSelector.class)) {
            // Candidate class is an ImportSelector -> delegate to it to determine imports
            Class<?> candidateClass = candidate.loadClass();
            ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
            ParserStrategyUtils.invokeAwareMethods(
                selector, this.environment, this.resourceLoader, this.registry);
            if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
              this.deferredImportSelectors.add(
                  new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
            }
            else {
              String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
              Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
              processImports(configClass, currentSourceClass, importSourceClasses, false);
            }
          }
          else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
            // Candidate class is an ImportBeanDefinitionRegistrar ->
            // delegate to it to register additional bean definitions
            Class<?> candidateClass = candidate.loadClass();
            ImportBeanDefinitionRegistrar registrar =
                BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
            ParserStrategyUtils.invokeAwareMethods(
                registrar, this.environment, this.resourceLoader, this.registry);
            configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
          }
          else {
            // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
            // process it as an @Configuration class
            this.importStack.registerImport(
                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
            processConfigurationClass(candidate.asConfigClass(configClass));
          }
        }
      }
      catch (BeanDefinitionStoreException ex) {
        throw ex;
      }
      catch (Throwable ex) {
        throw new BeanDefinitionStoreException(
            "Failed to process import candidates for configuration class [" +
            configClass.getMetadata().getClassName() + "]", ex);
      }
      finally {
        this.importStack.pop();
      }
    }
  }

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

相關(guān)文章

  • Java數(shù)據(jù)結(jié)構(gòu)超詳細(xì)分析二叉搜索樹(shù)

    Java數(shù)據(jù)結(jié)構(gòu)超詳細(xì)分析二叉搜索樹(shù)

    二叉搜索樹(shù)是以一棵二叉樹(shù)來(lái)組織的。每個(gè)節(jié)點(diǎn)是一個(gè)對(duì)象,包含的屬性有l(wèi)eft,right,p和key,其中,left指向該節(jié)點(diǎn)的左孩子,right指向該節(jié)點(diǎn)的右孩子,p指向該節(jié)點(diǎn)的父節(jié)點(diǎn),key是它的值
    2022-03-03
  • Java代碼注釋規(guī)范詳解

    Java代碼注釋規(guī)范詳解

    代碼附有注釋對(duì)程序開(kāi)發(fā)者來(lái)說(shuō)非常重要,隨著技術(shù)的發(fā)展,在項(xiàng)目開(kāi)發(fā)過(guò)程中,必須要求程序員寫(xiě)好代碼注釋,這樣有利于代碼后續(xù)的編寫(xiě)和使用。下面給大家分享java代碼注釋的規(guī)范,需要的朋友參考下
    2016-02-02
  • 詳解Java數(shù)組的定義和聲明方法

    詳解Java數(shù)組的定義和聲明方法

    在Java開(kāi)發(fā)中,數(shù)組是最常用的數(shù)據(jù)結(jié)構(gòu)之一,因此,深入了解Java數(shù)組的定義和聲明是非常必要的,本文將詳細(xì)介紹Java數(shù)組的定義和聲明方法,以及其在實(shí)際開(kāi)發(fā)中的應(yīng)用場(chǎng)景、優(yōu)缺點(diǎn)等方面,需要的朋友可以參考下
    2023-11-11
  • java中把漢字轉(zhuǎn)換成簡(jiǎn)拼的實(shí)現(xiàn)代碼

    java中把漢字轉(zhuǎn)換成簡(jiǎn)拼的實(shí)現(xiàn)代碼

    本篇文章是對(duì)在java中把漢字轉(zhuǎn)換成簡(jiǎn)拼的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • spring cloud 之 Feign 使用HTTP請(qǐng)求遠(yuǎn)程服務(wù)的實(shí)現(xiàn)方法

    spring cloud 之 Feign 使用HTTP請(qǐng)求遠(yuǎn)程服務(wù)的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇spring cloud 之 Feign 使用HTTP請(qǐng)求遠(yuǎn)程服務(wù)的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • MyBatis生成UUID的實(shí)現(xiàn)

    MyBatis生成UUID的實(shí)現(xiàn)

    這篇文章主要介紹了MyBatis生成UUID的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java 二維碼,QR碼,J4L-QRCode 的資料整理

    Java 二維碼,QR碼,J4L-QRCode 的資料整理

    本文主要介紹Java 中二維碼,QR碼,J4L-QRCode,這里整理了詳細(xì)的資料供大家學(xué)習(xí)參考關(guān)于二維碼的知識(shí),有需要的小伙伴可以參考下
    2016-08-08
  • 使用Nacos作為配置中心的命名空間、配置分組

    使用Nacos作為配置中心的命名空間、配置分組

    文章詳細(xì)介紹了Spring Cloud Config配置中心的命名空間、配置集、配置集ID、配置分組以及如何在微服務(wù)中加載和使用這些配置,通過(guò)配置中心,可以實(shí)現(xiàn)配置隔離和集中管理,簡(jiǎn)化微服務(wù)的配置維護(hù)
    2024-12-12
  • java解析xml的4種方式的優(yōu)缺點(diǎn)對(duì)比及實(shí)現(xiàn)詳解

    java解析xml的4種方式的優(yōu)缺點(diǎn)對(duì)比及實(shí)現(xiàn)詳解

    這篇文章主要介紹了java解析xml的4種方式的優(yōu)缺點(diǎn)對(duì)比及實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 利用Java實(shí)體bean對(duì)象批量數(shù)據(jù)傳輸處理方案小結(jié)

    利用Java實(shí)體bean對(duì)象批量數(shù)據(jù)傳輸處理方案小結(jié)

    javabean是對(duì)面向?qū)ο笏枷氲囊环N具體實(shí)施的表現(xiàn),本文重點(diǎn)給大家介紹利用Java實(shí)體bean對(duì)象批量數(shù)據(jù)傳輸處理方案小結(jié),本文通過(guò)兩種方案給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2021-05-05

最新評(píng)論

卢氏县| 师宗县| 甘洛县| 景东| 黄龙县| 贵德县| 大关县| 肇庆市| 勃利县| 巴东县| 合水县| 吕梁市| 临海市| 福泉市| 定日县| 怀宁县| 霍邱县| 南昌县| 尤溪县| 民县| 新干县| 堆龙德庆县| 繁昌县| 新化县| 西峡县| 泰顺县| 青浦区| 河津市| 六安市| 西宁市| 惠安县| 博客| 留坝县| 仁布县| 贵德县| 天台县| 白银市| 墨竹工卡县| 英超| 兴仁县| 道真|