激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務(wù)器之家 - 編程語言 - Java教程 - Springboot @Import 詳解

Springboot @Import 詳解

2021-06-17 11:15愛笑的咖啡 Java教程

這篇文章主要介紹了Springboot @Import 詳解,仔細(xì)看了下Springboot關(guān)于@Import的處理過程,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

springboot 的 @import 用于將指定的類實(shí)例注入之spring ioc container中。 

今天抽空在仔細(xì)看了下springboot 關(guān)于 @import 的處理過程, 記下來以后看。

1. @import

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
 * 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é)下來就是需要通過這個(gè)接口的實(shí)現(xiàn)去決定要引入哪些 @configuration。 它如果實(shí)現(xiàn)了以下四個(gè)aware 接口, 那么spring保證會(huì)在調(diào)用它之前先調(diào)用aware接口的方法。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * 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注解的處理過程

springboot對(duì)注解的處理都發(fā)生在abstractapplicationcontext -> refresh() -> invokebeanfactorypostprocessors(beanfactory) -> configurationclasspostprocessor -> postprocessbeandefinitionregistry()方法中。

(稍微說下也免得我自己忘了, springboot初始化的普通context(非web) 是annotationconfigapplicationcontext, 在初始化的時(shí)候會(huì)初始化兩個(gè)工具類, annotatedbeandefinitionreader 和 classpathbeandefinitionscanner 分別用來從 annotation driven 的配置和xml的配置中讀取beandefinition并向context注冊(cè), 那么在初始化 annotatedbeandefinitionreader 的時(shí)候, 會(huì)向beanfactory注冊(cè)一個(gè)configurationclasspostprocessor 用來處理所有的基于annotation的bean, 這個(gè)configurationclasspostprocessor 是 beanfactorypostprocessor 的一個(gè)實(shí)現(xiàn),springboot會(huì)保證在  invokebeanfactorypostprocessors(beanfactory) 方法中調(diào)用注冊(cè)到它上邊的所有的beanfactorypostprocessor)

如下代碼顯示是通過 configurationclassparser 類來轉(zhuǎn)換的

?
1
2
3
4
// 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í)候是通過遞歸處理來保證所有的都被處理了)

?
1
2
// process any @import annotations
    processimports(configclass, sourceclass, getimports(sourceclass), true);

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

  首先, 判斷如果被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è)正常的類來處理 ( 調(diào)用最外層的doprocessconfigurationclass())

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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í)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.cnblogs.com/hermanlife/p/10019473.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美精品在线免费观看 | 日本不卡二区 | 黄色羞羞视频在线观看 | 国产免费片 | 国产成人精品区一区二区不卡 | 毛片在哪里看 | 欧美国产日韩在线 | 黄视频免费观看 | 久久精品一区二区三区不卡牛牛 | 九九热国产视频 | 久久久久夜色精品国产老牛91 | 色妞视频男女视频 | 国产精选电影免费在线观看 | 欧美亚洲一区二区三区四区 | 97久色| 意大利av在线 | 欧美三级一级 | 久久婷婷一区二区三区 | 成人免费av在线 | 黄色男女视频 | 久久久av亚洲男天堂 | 亚洲精品午夜国产va久久成人 | 久久久久国产精品久久久久 | 黄色99视频 | 一级啪啪片 | 黄色网址免费在线播放 | 97中文 | v11av在线播放| 欧美成人一级片 | 深夜影院a | 免费a级毛片大学生免费观看 | 草莓福利视频在线观看 | 欧美一级黄色免费 | 久久久久久久久久久久免费 | 黄视频免费在线观看 | 欧美一级高潮 | 国产精品久久久久久久久久久久久久久 | 久久999精品久久久 国产噜噜噜噜久久久久久久久 | 亚洲欧美国产高清va在线播放 | 操碰97 | 性猛交ⅹxxx乱巴西 在线播放中文 |