最初の接触は、ばねの基礎となっているときだけで双方向のパッケージを引用して、バックエンドの開発を行うことも、私たちは、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.factories
のEnableAutoConfiguration
豆の関連するクラスを、第二は、春のコンテナにクラス登録を取得することです。
クラスコレクションの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の場合は、消費者が使用することができ除外プロパティを。@EnableAutoConfiguration
exclude
私は、Java、Redisを、MongoDBのは、MySQL、カバー、無料のJavaの詳細情報をコンパイルしたダボは、飼育係、春の雲を、30Gの合計を高い並行性と他のチュートリアルを配布し、独自のコレクションを必要とします。
ポータル:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q