春ブーツ@EnableAutoConfiguration解析

最初の接触は、ばねの基礎となっているときだけで双方向のパッケージを引用して、バックエンドの開発を行うことも、私たちは、XMLに対応したパケットを増やす必要があり、Beanを提供し<context:component-scan base-package="xxx" /> たりメモを追加します@ComponentScan({ "xxx"})私は非常にurgly感じたが、そこより良い方法を勉強しに行きませんでした。

春ブーツまで接触した後、Beanは自動的に2番目のパーティのパッケージを組み込むことが判明しました。しかし、私はこの原則の実現を見ませんでした。最近まで、とき面接について尋ねました。だから私は、実装ロジックの下に見えました。

 

ジェスチャーを使用してください

最初の原則の下で、使用姿勢の前に話します。

豆は、プロジェクトAで定義されました。

パッケージcom.wangzhi。

輸入org.springframework.stereotype.Service。

@Service 
パブリック クラス犬{ 
}

 

そして、プロジェクトがあるresources/META-INF/の下の名前を作成するためにspring.factories、次のように文書を読み込み、文書

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

 

プロジェクトBに続いて、参照プロジェクトのjarパッケージ

次のようにPROJECTAコードは次のとおりです。

パッケージcom.wangzhi.springbootdemo。

輸入org.springframework.boot.SpringApplication。
輸入org.springframework.boot.autoconfigure.EnableAutoConfiguration。
輸入org.springframework.boot.autoconfigure.SpringBootApplication。
輸入org.springframework.context.ConfigurableApplicationContext。
輸入org.springframework.context.annotation.ComponentScan; 

@EnableAutoConfiguration 
パブリック クラスSpringBootDemoApplication { 

    公共 静的 ボイドメイン(文字列[]引数){ 
        ConfigurableApplicationContextコンテキスト = SpringApplication.run(SpringBootDemoApplication。クラス、引数)。
        System.out.println(context.getBean(com.wangzhi.Dog。クラス)); 
    } 

}

 

印刷結果:

com.wangzhi.Dog@3148f668

 

分析の原則

全体的に二つの部分に分かれています。まず、すべての収集spring.factoriesEnableAutoConfiguration豆の関連するクラスを、第二は、春のコンテナにクラス登録を取得することです。

クラスコレクションのBean定義

コンテナの起動時に春には、それがために呼び出しますAutoConfigurationImportSelector#getAutoConfigurationEntry

保護されたAutoConfigurationEntry getAutoConfigurationEntry(
        AutoConfigurationMetadata autoConfigurationMetadata、
        AnnotationMetadata annotationMetadata){ 
    場合(!ISENABLED(annotationMetadata)){
         返すEMPTY_ENTRYを。
    } 
    // EnableAutoConfiguration注解的属性:、excludeName等除外 
    AnnotationAttributesは=属性のgetAttributesを(annotationMetadata)。
    // 得到所有的構成の 
    一覧<文字列>構成= getCandidateConfigurations(annotationMetadata、
            属性); 
    // 去重 
    構成=removeDuplicates(構成)。
    // 删除掉中指定的类除外 
    設定<文字列>除外=のgetExclusions(annotationMetadata、属性); 
    checkExcludedClasses(構成、除外)。
    configurations.removeAll(除外)。
    構成 = フィルタ(構成、autoConfigurationMetadata)。
    fireAutoConfigurationImportEvents(構成、除外)。
    返す 新しいAutoConfigurationEntry(構成、除外)。
} 
getCandidateConfigurations会调用到方法loadFactoryNames:

公共の 静的リストの<string> loadFactoryNames(<?>クラスfactoryClass、@NullableのClassLoaderクラスローダー){
        // factoryClassName为org.springframework.boot.autoconfigure.EnableAutoConfiguration 
        ストリングfactoryClassName = factoryClass.getName()。
        // 该方法返回的是所有spring.factories文件中キー为org.springframework.boot.autoconfigure.EnableAutoConfiguration的类路径
        リターンloadSpringFactories(クラスローダー).getOrDefault(factoryClassName、Collections.emptyList()); 
    } 


公共の 静的な 最終文字列FACTORIES_RESOURCE_LOCATION = "META-INF / spring.factories" 

プライベート 静的な地図<文字列、リスト<文字列>> loadSpringFactories(@Nullableクラスローダクラスローダ){ 
        MultiValueMap <文字列、文字列>結果=cache.get(クラスローダー)。
        もし(!結果= nullの){
             戻り値の結果; 
        } 

        してみてください{
             // 找到所有的"META-INF / spring.factories" 
            列挙<URL> URLをする=(!クラスローダ= nullの
                    classLoader.getResources(FACTORIES_RESOURCE_LOCATION):
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); 
            結果 = 新しい LinkedMultiValueMap <> ();
            一方、(urls.hasMoreElements()){ 
                URLのURL = urls.nextElement()。
                UrlResourceリソース = 新新UrlResource(URLを);
                 //は、キー属性と値を含むファイルの内容、HashMapのと同様の性質、読み 
                プロパティプロパティ= PropertiesLoaderUtils.loadProperties(リソース);
                 のため(のMap.Entry <?、?> エントリー: properties.entrySet()){ 
                    文字列factoryClassName = ((文字列)entry.getKey()))(TRIM;
                     // 属性ファイルを使用することができる''分割された値の複数
                    のために(文字列をfactoryName:StringUtils.commaDelimitedListToStringArray((文字列)entry.getValue())){ 
                        result.add(factoryClassName、factoryName.trim())。 
                    } 
                } 
            } 
            cache.put(クラスローダ、結果)。
            戻り値の結果; 
        } 
        キャッチ(のIOExceptionのEX){
             スロー 新しい( "[+場所から工場をロードできません"、IllegalArgumentExceptionを
                    FACTORIES_RESOURCE_LOCATION + "]" 、EX)。
        } 
    }

 

コンテナにサインアップ

上記工程で得られた全spring.factories豆のパスで指定されたクラスは、processGroupImportsプロセスが処理される@import同じ容器に導入注釈ロジック。

公共 ボイドprocessGroupImports(){
     ため:(GROUPINGをDeferredImportSelectorGrouping この{.groupings.values())
         // 上記で得られたすべてのパスカプセル化getImportsすなわちクラス 
        > - grouping.getImportsを()のforEach(エントリ{ 
            ConfigurationClass configurationClass = この.configurationClasses .get(
                    entry.getMetadata()); 
            試み{
                 // @importとして、プロセスアノテーション
                processImports(configurationClass、asSourceClass(configurationClass)、
                        asSourceClasses(entry.getImportClassName())、偽へ)。
            }
            キャッチ(BeanDefinitionStoreExceptionの例){
                 スローEX。
            } 
            キャッチ(ThrowableのEX){
                 スロー 新しい(BeanDefinitionStoreExceptionを
                         "[+コンフィギュレーションクラスのインポート候補の処理に失敗しました" 
                                configurationClass.getMetadata()getClassNameメソッド() + "]" 、EX)。
            } 
        })。
    } 
} 

プライベート 無効processImports(ConfigurationClass configClass、sourceClassをcurrentSourceClass、
            コレクション <sourceClassを> importCandidates、ブールcheckForCircularImports){ 
    ... 
    // 収集クラスパストラバース
    (sourceClassを候補:importCandidatesを){ 
       ... 
        // 候補がImportSelector ImportBeanDefinitionRegistrarであるか、処理ロジックのタイプは異なるものになる場合は、ここでは関係ありません
          // 候補クラスではありませんまたはImportBeanDefinitionRegistrar ImportSelector - >
                         // プロセスクラスIT @Configuration AS 
                        この.importStack.registerImport(
                                currentSourceClass.getMetadata()、candidate.getMetadata()getClassNameメソッド()); 
        // @Configuration処理として            
         processConfigurationClass(candidate.asConfigClass (configClass))。
   ... 
} 
            
    ... 
}

 

Beanクラスに収集定義最初のステップは、最終的になり見ることができるConfiguration容器に登録同じ処置。

終わり

@EnableAutoConfiguration注釈第二当事者は単純化された豆のパッケージコストを導入しました。第二者は、他のアプリケーション、外部Bean定義にさらされるだけ二次会バッグ提供する契約を結んでspring.factoriesちょうど罰金を。不要なBeanの場合は、消費者が使用することができ除外プロパティを。@EnableAutoConfigurationexclude

 

私は、Java、Redisを、MongoDBのは、MySQL、カバー、無料のJavaの詳細情報をコンパイルしたダボは、飼育係、春の雲を、30Gの合計を高い並行性と他のチュートリアルを配布し、独自のコレクションを必要とします。
ポータル:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

おすすめ

転載: www.cnblogs.com/yuxiang1/p/11331727.html