Springbootの自動アセンブリは、ボックス化の根拠とマイクロサービスの前提条件です。今回の主なトピックは、それがどのように実装されるかを見ることです。ソースコードを使用して、自動アセンブリのインとアウトを把握します。
1.1。 @SpringBootApplicationについて
Springboot Projectを書いているとき、@SpringBootApplicationが最も一般的な注釈です。ソースコードをご覧ください。
/ * *著作権2012-2017元の著者または著者。 * * Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。 *ライセンスに準拠している場合を除き、このファイルを使用することはできません。 *ライセンスのコピーを取得することができます * * http://www.apache.org/licenses/license-2.0 * *該当する法律で要求されていない場合、または書面で合意しない限り、ライセンスに基づいて配布されるソフトウェア *は、保証または条件なしで「現状」に分配されます。 *特定の言語ガバナンス許可のライセンスとライセンスに基づく制限を参照してください。 */package org.springframework.boot.autoconfigure; import java.lang.annotation.documented; import java.lang.annotation.ElementType; Import java.lang.annotation.inherite.inherite; Import Java.lang.Annotation.retention; import java.lang.lang.annotation; retingtation; retingtation; java.lang.annotation.target; Import org.springframework.boot.springbootconfiguration; Import org.springframework.boot.context.typeexcludefilter; Import org.springframework.context.annotation.bean; Import framework.contextation.notation.context.contextation org.springframework.context.componentscan.filter; import org.springframework.context.annotation.configuration; Import org.springframework.context.annotation.filtertype; import org.springframework.core.coration.coration.Annotation.Annotation.Annotation.Annotation.Annotation.Annotation.Annotation.Annotation.Annotation.Annotation.Annotation 1つ以上の * {@link bean @bean}メソッドを宣言し、{@link enableautoconfiguration * auto-configuration}および{@link Componentscanコンポーネントスキャン}をトリガーするクラス。これは、{@code @configuration}、 * {@code @enableautoconfiguration}、{@code @componentscan}を宣言することに相当する便利な *注釈です。 * * @Author Phillip Webb * @Author Stephane Nicoll * @since 1.2.0 */@ターゲット(elementType.type)@retention(retentionPolicy.runtime)@documented@springbootconfiguration@enableautoconfiguration@componentscan(excludefilters =@@filtom、filtertype.custpe. typeexcludefilter.class)、@filter(type = filtertype.custom、classes = autoconfigurationexcludefilter.class)})public @interface springbootApplication { /***適用されないような特定の自動構成クラスを除外します。 * @ @return exclude */ @aliasfor(annotation = enableautoconfiguration.class、aTtible = "exclude")class <?> [] exclude()default {}; /** *特定の自動構成クラス名を除外して、それらが決して適用されないようにします。 * @@return exclude * @since 1.3.0 */ @aliasfor(annotation = enableautoconfiguration.class、aTtribute = "excludename")string [] exprodename()default {}; /***注釈付きコンポーネントをスキャンするベースパッケージ。 {@link #scanbasepackageClasses} *を使用して、文字列ベースのパッケージ名に代わるタイプセーフの代替品を使用します。 * @return scan to scanのベースパッケージ * @since 1.3.0 */ @aliasfor(annotation = componentscan.class、aTtribute = "basepackages")string [] scanbasepackages()default {}; /** *注釈付きコンポーネントをスキャンするパッケージを指定するための{@link #scanbasepackages}のタイプセーフの代替。指定された各クラスのパッケージはスキャンされます。 * <p> *各パッケージに特別なノーオップマーカークラスまたはインターフェイスを作成することを検討してください。 * @return scan to scan * @since 1.3.0 */ @aliasfor(annotation = componentscan.class、attribute = "basepackageclasses")class <?> [] scanbasepackageclasses()default {};}これには、@springBootConfiguration、 @enableautoconfiguration、@componentscanが含まれています。ここでは、スキャンパッケージが指定されていないため、デフォルトでクラスと同じレベルまたは同じレベルのパッケージと同じレベルですべてのクラスをスキャンします。さらに、@springBootConfigurationでは、ソースコードを介して@Configuration:であることがわかります。
/ * * Copyright 2012-2016元の著者または著者。 * * Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。 *ライセンスに準拠している場合を除き、このファイルを使用することはできません。 *ライセンスのコピーを取得することができます * * http://www.apache.org/licenses/license-2.0 * *該当する法律で要求されていない場合、または書面で合意しない限り、ライセンスに基づいて配布されるソフトウェア *は、保証または条件なしで「現状」に分配されます。 *特定の言語ガバナンス許可のライセンスとライセンスに基づく制限を参照してください。 */package org.springframework.boot; import java.lang.annotation.documented; import java.lang.annotation.elementtype; import java.lang.annotation.retention; import java.lang.annotation.RetentionPolicy; Import Java.lang.Annotation; Import; Import; org.springframework.context.annotation.configuration;/** *クラスがSpring Bootアプリケーションを提供していることを示します * {@link Configuration @Configuration}。 Springの * Standard {@code @configuration}アノテーションの代替として使用できるように、構成を自動的に見つけることができます(たとえば、テストで)。 * <p> *アプリケーションには、<em> 1つの</em> {@code @springbootconfiguration}を含める必要があります。 * * @author phillip webb * @since 1.4.0 */@target(elementtype.type)@retention(retentionPolicy.runtime)@documentded@configurationPublic @interface springbootconfiguration {}これから、@springbootapplicationは@configuration @componentscan @enableautoconfigurationと同等であると推測できます
1.2。 @enableautoconfiguration
この注釈が追加されると、自動アセンブリ関数が有効になります。簡単に言えば、SpringはClassPathの下で構成されたすべての豆を見つけてから組み立てます。もちろん、Beanを組み立てるときは、いくつかの(条件付き)カスタマイズルールに従って初期化されます。ソースコードを見てみましょう。
/ * *著作権2012-2017元の著者または著者。 * * Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。 *ライセンスに準拠している場合を除き、このファイルを使用することはできません。 *ライセンスのコピーを取得することができます * * http://www.apache.org/licenses/license-2.0 * *該当する法律で要求されていない場合、または書面で合意しない限り、ライセンスに基づいて配布されるソフトウェア *は、保証または条件なしで「現状」に分配されます。 *特定の言語ガバナンス許可のライセンスとライセンスに基づく制限を参照してください。 */package org.springframework.boot.autoconfigure; import java.lang.annotation.documented; import java.lang.annotation.ElementType; Import java.lang.annotation.inherite.inherite; Import Java.lang.Annotation.retention; import java.lang.lang.annotation; retingtation; retingtation; java.lang.annotation.target; Import org.springframework.boot.autoconfigure.conditionalonbean; Import org.springframework.boot.autoconfigure.condition.conditionalonbean; Import org.springframework.boot.autoconfigure.condition.conditionalonmissingbean; Import org.springframework.boot.context.embedded.embeddedservletcontainerfactory; Import org.springframework.boot.context.embedded.tomcat.tomcatembeddedservletcontainerfactory; Import.springframework.context.annotation.conditional; Import org.springframework.context.annotation.configuration; intpringframework org.springframework.core.io.support.support.springfactoriesloader;/** *スプリングアプリケーションコンテキストの自動構成を有効にします。自動構成クラスは、通常、クラスパスと定義した豆に基づいて *適用されます。たとえば、{@code tomcat-embedded.jar}をクラスパスに持っている場合、a * {@link tomcatembeddedservletcontainerfactory}が必要になる可能性が高い(@link beddedservletcontainerfactory} beanを定義していない限り)。 * <p> * {@link SpringBootApplication}を使用すると、コンテキストの自動構成が自動的に有効になり、この注釈を追加すると追加の効果はありません。 * <p> *自動構成は、可能な限りインテリジェントになろうとし、自分の構成をより多く定義するにつれて後退します。手動で{@link #exclude()}任意の *適用したくない[{@link #excludename()}を使用しない場合はいつでもできます)。 * {@code spring.autoconfigure.exclude}プロパティを介してそれらを除外することもできます。ユーザー定義の豆が登録された後、自動構成は常に適用されます *。 * <p> * {@code @enableautoconfiguration}で注釈が付けられたクラスのパッケージ、 *通常は{@code @springbootapplication}を介して、特定の重要性を持ち、しばしば「デフォルト」として使用されます。たとえば、{@code @Entity}クラスのスキャン時に使用されます。 *一般に、すべてのサブパッケージ *とクラスを検索できるように、{ @code @enableautoconfiguration}({@code @springbootapplication}を使用していない場合)をルートパッケージに使用していない場合はお勧めします。 * <p> *自動構成クラスは、通常のSpring {@link Configuration}豆です。 {@link springFactoriesLoader}メカニズム(このクラスにキー付き)を使用して *位置しています。 *一般的に自動コンフィグラー豆は{@link conditional @conditional}豆(ほとんど * @link conditionalonclass @conditionalonclass}を使用していることが多く、 * {@link cosditionalonmissingbean @conditionalonmissingbean}解決)です。 * * @Author Phillip Webb * @Author Stephane Nicoll * @see ConditionAlonbean * @see ConditionAlonMissingbean * @see ConditionAlonClass * @see autoconfigureaffter * @see springbootapplication */@suppresswarnings( "deprecation")@target(elementType.type)@retention(retentionPolicy.runtime)@documented@enternited@autoconfigurationpackage@import(enableautoconfigurationimportselector.class)public @interface enableautoconfiguration {Strined_override_property = 「spring.boot.enableautoconfiguration」; /***特定の自動構成クラスを除外して、適用されないようにします。 * @returnクラスを除外する */ class <?> [] exclude()default {}; /** *特定の自動構成クラス名を除外して、それらが決して適用されないようにします。 * @@return exclude * @since 1.3.0 */ string [] expludename()default {};}ドキュメントのコメントによると、Inableautoconfigurationimportselectorを見るように導きます。しかし、クラスはSpringboot1.5.xバージョンで時代遅れですので、親クラスのautoconfigurationimportsecreを見てみましょう。
/ * *著作権2012-2017元の著者または著者。 * * Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。 *ライセンスに準拠している場合を除き、このファイルを使用することはできません。 *ライセンスのコピーを取得することができます * * http://www.apache.org/licenses/license-2.0 * *該当する法律で要求されていない場合、または書面で合意しない限り、ライセンスに基づいて配布されるソフトウェア *は、保証または条件なしで「現状」に分配されます。 *権限を管理する特定の言語のライセンスと、ライセンスに基づく制限を参照してください。 */package org.springframework.boot.autoconfigure; import java.io.ioexception; Import java.util.arraylist; Import java.util.arrays; Import java.util.collection; import java.util.hashset; import java.util.util.util.util.util.til. java.util.map; Import java.util.set; import java.util.concurrent.timeunit; Import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; import org.springframework.beansexception; Beans.Factory.BeanClassLoaderAware; Import org.springframework.beans.factory.beanfactory; Import org.springframework.beans.factory.beanfactoryaware; Import org.springframework.beans.factory.nosuchbeanditionexception; org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.boot.bind.RelaxedPropertyResolver;import org.springframework.context.EnvironmentAware;import org.springframework.context.ResourceLoaderAware;import org.springframework.annotation.deferredimportselector; Import org.springframework.core.ordered; Import org.springframework.core.annotation.annotation.annotationAttributes; Import org.springframework.core.env.configurableenvironment; springframework.core.env.environment; Import org.springframework.core.io.resourceloader; Import org.springframework.core.io.io.support.springfactoriesloader; Import org.springframework.core.tpe.annotationmetadata; org.springframework.type.classreading.cachingmetadatareaderfactory; import org.springframework.core.type.classreading.metadatareaderfactory; Import org.springframework.util.assert; Import org.utilwork.util.util.classutils; org.springframework.util.stringutils;/** * {@link deferredimportselector} {@link enableautoconfiguration * auto-configuration}。このクラスは、 * {@link enableautoconfiguration @enableautoconfiguration}のカスタムバリアントの場合にもサブクラス化できます。必要です。 * * @Author Phillip Webb * @Author Andy Wilkinson * @Author Stephane Nicoll * @Author Madhura Bhave * @since 1.3.0 * @see enableautoconfiguration */Public Class autoconfigurationimportsecre {private static final string [] no_imports = {}; private static final logger = logFactory .getLog(autoconfigurationimportsecrecect.class); private configurablelistablebeanFactory BeanFactory;民間環境環境;プライベートクラスローダーBeanClassloader; Private Resourceoader resourceLeceloader; @Override public String [] selectimports(annotationmetadata annotationmetadata){if(!isenabled(annotationmetadata)){return no_imports; } try {autoconfigurationmetadata autoconfigurationmetadata = autoconfigurationmetadataloader .loadmetadata(this.beanclassoloader); annotationAttributes属性= getattributes(annotationmetadata); List <String> Configurations = getCandidateConFigurations(AnnotationMetadata、属性);構成= removeduplicates(構成);構成= sort(configurations、autoconfigurationmetadata); SET <String>除外= getExclusions(annotationmetadata、属性); checkexcludedclasses(構成、除外); Configurations.RemoveAll(除外); configurations = filter(configurations、autoconfigurationmetadata); fireautoconfigurationimportevents(構成、除外); configurations.toarray(new String [configurations.size()]); } catch(ioException ex){新しいIllegalStateException(ex); }}保護されたboolean isEnabled(annotationmetadata metadata){return true; } /** * * {@link annotationmetadata}から適切な{@link annotationattributes}を返します。デフォルトでは、このメソッドは * {@link #getannotationClass()}の属性を返します。 * @param metadata annotation metadata * @return annotation属性 */ protected annotationattributes getattributes(annotationmetadata metadata){string name = getAnnotationClass()。getName(); annotationAttributes attributes = annotationAttributes .frommap(metadata.getannotationattributes(name、true)); assert.notnull(属性、 "auto configuration属性は見つかりません。" + metadata.getClassName() + " + classutils.getShortName(name) +"? ");返品属性。 } /***セレクターが使用するソースアノテーションクラスを返します。 * @return annotation class */ protected class <?> getAnnotationClass(){return enableautoconfiguration.class; } /***考慮すべき自動コンフィグレーザークラス名を返します。デフォルトでは *このメソッドは、 * {@link #getSpringFactoriesLoaderFactoryClass()}と{@Link SpringFactoriesLoader}を使用して候補をロードします。 * @param metadataソースメタデータ * @param属性{@link #getattributes(annotationmetadata)annotation *属性} * @return候補構成のリスト</保護されたリスト<文字列> getCandidateConfigurations(annotationmetadata metatadata annotatadata、annotatadata annotatadata SpringFactoriesLoader.LoadFactoryNames(getSpringFactoriesLoaderFactoryClass()、getBeanClassLoader()); assert.notempty(configurations、 "Meta-inf/spring.Factoriesで見つかった自動構成クラスはありません。「 +」がカスタムパッケージを使用している場合は、ファイルが正しいことを確認してください。」);構成を返す; } /** * {@link springFactoriesLoader}で使用されているクラスを返して、候補者をロードします。 * @return The Factory Class */ Protected Class <?> } private void checkexcludedClasses(list <string> configurations、set <string>除外){list <string> invalidexcludes = new arraylist <string>(explusions.size()); for(string除外:explus){if(classutils.ispresent(explusion、getClass()。getClassLoader())&&!configurations.contains(exclusion)){invalidexcludes.add(explusion); }} if(!invalidexcludes.isempty()){handleinvalidexcludes(invalidexcludes); }} /***指定された無効な除外を処理します。 * @param InvalidexCludes無効な除外のリスト(常に少なくとも1つの *要素があります) for(string exclude:invalidexcludes){message.append( "/t-").append(exclude).append(string.format( "%n")); }新しいIllegalStateException(string .format( "自動構成クラスではない」 +" + "n%s"、メッセージ)を投げることはできませんでした。 } /***候補構成を制限する除外を返します。 * @param metadataソースメタデータ * @param属性{@link #getattributes(annotationmetadata)annotation *属性} * @return除外 */保護されたセット<文字列> getexclusions(annotationmetadata metadata、annotationattributesttributesttributestributettributedata) LinkedHashset <String>(); explued.addall(aslist(astributes、 "exclude")); explued.addall(arrays.aslist(astributes.getStringArray( "excludename"))); explued.addall(getexcludeautoconfigurationsproperty());除外された返品。 } private list <string> getExcludeautoconfigurationsproperty(){if(getEnvironment()configurableenvironmentのインスタンス){rackedpropertyResolver Resolver = new raxedpropertyResolver(this.environment、 "spring.autoconfigure。"); map <string、object> properties = resolver.getsubproperties( "exclude"); if(properties.isempty()){return collections.emptylist(); } list <string> excludes = new ArrayList <String>(); for(map.entry <string、object> entry:properties.entryset()){string name = entry.getKey();オブジェクト値= entry.getValue(); if(name.isempty()|| name.startswith( "[")&& value!= null){expludes.addall(new hashset <string>(arrays.aslist(stringutils .tokenizetostring))); }} return excludes; } RelaxedPropertyResolver Resolver = new RelaxedPropertyResolver(getEnvironment()、 "Spring.AutoconFigure。"); string [] exclude = resolver.getProperty( "exclude"、string []。class); return(arrays.aslist(exclude == null?new String [0]:exclude)); } private list <string> sort(list <string> configurations、autoconfigurationmetadata autoconfigurationmetadata)throws ioexception {configurations = new autoconfigurationsortor(getMetadatareaderFactory()、autoconfigurationmetadata).getinpriorityOrdation(Confucations);構成を返す; }プライベートリスト<String>フィルター(リスト<String> Configurations、autoconfigurationMetadata autoconfigurationmetadata){long starttime = system.nanotime(); string [] condations = configurations.toarray(new String [configurations.size()]); boolean [] skip = new boolean [condatis.length]; booleanスキップ= false; for(autoconfigurationimportfilterフィルター:getautoconfigurationimportfilters()){invokeawaremethods(filter); boolean [] match = filter.match(候補者、autoconfigurationmetadata); for(int i = 0; i <match.length; i ++){if(!match [i]){skip [i] = true;スキップ= true; }}}} if(!skippip){return configurations; } list <String> result = new ArrayList <String>(constaties.length); for(int i = 0; i <condations.length; i ++){if(!skip [i]){result.add(condations [i]); }} if(logger.istraceEnabled()){int numberfiltered = configurations.size() - result.size(); logger.trace( "filtered" + numberfiltered + "auto configuration class in" + timeunit.nanoseconds.tomillis(system.nanotime() - starttime) + "ms"); } new arrayList <String>(result)を返します。 }保護されたリスト<autoconfigurationimportfilter> getautoconfigurationimportfilters(){return springfactoriesloader.loadfactories(autoconfigurationimportfilter.class、this.beanclassloader); } private metadatareaderfactory getMetAdatareAderFactory(){try {return getBeanFactory()。getBean(sharedmetadatareaderfactorycontextinitializer.bean_name、metadatareaderfactory.class); } catch(nosuchbeandefinitionException ex){return new cachingmetadatareaderfactory(this.resourceloader); }}保護された最終<t>リスト<t> remodeveduplicates(list <t> list){return new arraylist <t>(new linkedhashset <t>(list)); }保護された最終リスト<String> aslist(annotationAttributes attributes、string name){string [] value = attributes.getStringArray(name); return arrays.aslist(value == null?new String [0]:value); } private void fireautoconfigurationimportevents(list <string> configurations、set <string> excclusions){list <autoconfigurationimportlistener>リスナー= getautoconfigurationimportlisteners(); if(!riessers.isempty()){autoconfigurationimportevent event = new autoconfigurationimportevent(this、configurations、excclusions); for(autoconfigurationimportlistenerリスナー:リスナー){invokeawaremethods(リスナー); listener.onautoconfigurationimportevent(event); }}} protected list <autoconfigurationimportlistener> getautoconfigurationimportlisteners(){return springfactoriesloader.loadfactories(autoconfigurationimportlistener.class、this.beanclassoloader); } private void invokeawaremethods(object instance){if(instance instanceof aware){if(instance instance of beanclassloaderaware){((beanclassloaderaware)instance).setbeanClassoloader(this.beanclassoloader); } if(instance of beanfactoryaware){((beanfactoryaware)instance).setBeanFactory(this.beanFactory); } if(Instance of EnvironmentAware){((EnvironmentAware)Instance).SetenVironment(this.environment); } if(Instance of resourceLoaderaware){((resourceLeCeladeraware)instance).setResourceloAder(this.ResourCeloAder); }}} @Override public void setBeanFactory(BeanFactory BeanFactory)BeanSexception {assert.isInstanceof(configureablelistablebeanfactory.class、beanfactory); this.beanfactory =(configureableLeListableBeanFactory)BeanFactory; } protected final configurablelistablebeanfactory getBeanFactory(){return this.beanFactory; } @Override public void setBeanClassloader(classloader classloader){this.beanclassloader = classloader; } protected classloader getBeanClassLoader(){return this.beanClassloader; } @override public void setenvironment(環境環境){this.environment =環境; }保護された最終環境getEnvironment(){return this.environment; } @Override public void setResourceloAder(resourceLeder resourceoader){this.resourceloader = resourceloader; }保護された最終的なResourceloAder getResourCeloAder(){return this.resourceloader; } @Override public int getOrder(){return ordered.lowest_precedence -1; }}まず、このクラスは、インポートセレクターを継承するdeferredimportselectorインターフェイスを実装しています。
/ * * Copyright 2002-2013元の著者または著者。 * * Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。 *ライセンスに準拠している場合を除き、このファイルを使用することはできません。 *ライセンスのコピーを取得することができます * * http://www.apache.org/licenses/license-2.0 * *該当する法律で要求されていない場合、または書面で合意しない限り、ライセンスに基づいて配布されるソフトウェア *は、保証または条件なしで「現状」に分配されます。 *権限を管理する特定の言語のライセンスと、ライセンスに基づく制限を参照してください。 */package org.springframework.context.annotation; import org.springframework.core.type.annotationmetadata;/** *インターフェイスは、 @{ @link configuration} *クラス(es)を決定するタイプによって実装されるインターフェイスを選択します。 * * <p> {@link importSecrecer}は、次のいずれかを実装できます * {@link org.springframework.beans.factory.aware aware}インターフェイス、およびそれぞれの *メソッドは{@link #selectimports}の前に呼び出されます。 EnvironmentAware} </li> * <li> {@link org.springframework.beans.factory.beanfactoryaware beanfactoryaware} </li> * <lig.springframework.beans.factory.factory.beanclassloaderaware beanclassolaser} org.springframework.context.resourceloaderaware resourceaderaware} </li> * </ul> * <p>インポートセレクトルは通常、通常の{@code @import} *アノテーションと同じ方法で処理されますが、すべての輸入の選択を延期することもできます。詳細については、DeferredimportSelector} * *。 * * @author chris beams * @since 3.1 * @see deferredimportselector * @seeeme import * @see intermedebeandefinitionregistrar * @see configuration * /public interface importselector { /** *クラス(es)の名前を選択して返す必要があります。 */ string [] selectimports(annotationmetadata ImportingClassMetadata);}このインターフェイスは、主に@configurationの構成項目をインポートするために使用され、Deferredimportselectorは延期されたインポートであり、@Configurationsがすべて処理された後にのみ実行されます。
autoconfigurationimportsecrecerのselectimportメソッドを見てみましょう。
@Override public String [] selectimports(annotationmetadata annotationmetadata){if(!isenabled(annotationmetadata)){return no_imports; } try {autoconfigurationmetadata autoconfigurationmetadata = autoconfigurationmetadataloader .loadmetadata(this.beanclassoloader); annotationAttributes属性= getattributes(annotationmetadata); List <String> Configurations = getCandidateConFigurations(AnnotationMetadata、属性);構成= removeduplicates(構成);構成= sort(configurations、autoconfigurationmetadata); set <string> excclusions = getExclusions(annotationmetadata、属性); checkexcludedclasses(構成、除外); Configurations.RemoveAll(除外); configurations = filter(configurations、autoconfigurationmetadata); fireautoconfigurationimportevents(構成、excclusions); configurations.toarray(new String [configurations.size()]); } catch(ioException ex){新しいIllegalStateException(ex); }}
最初は、この方法では、最初に自動アセンブリを実行するかどうかを決定し、次にメタデータとメタデータの関連する特性をメタINF/Spring-AutoconFigure-Metadata.Propertiesから読み取り、GetCandidateConfigureationsメソッドを呼び出します。
/***考慮すべき自動コンフィグレーザークラス名を返します。デフォルトでは *このメソッドは、 * {@link #getSpringFactoriesLoaderFactoryClass()}と{@Link SpringFactoriesLoader}を使用して候補をロードします。 * @param metadataソースメタデータ * @param属性{@link #getattributes(annotationmetadata)annotation *属性} * @return候補構成のリスト</保護されたリスト<文字列> getCandidateConfigurations(annotationmetadata metatadata annotatadata、annotatadata annotatadata SpringFactoriesLoader.LoadFactoryNames(getSpringFactoriesLoaderFactoryClass()、getBeanClassLoader()); assert.notempty(configurations、 "Meta-inf/spring.Factoriesで見つかった自動構成クラスはありません。「 +」がカスタムパッケージを使用している場合は、ファイルが正しいことを確認してください。」);構成を返す; } /** * {@link springFactoriesLoader}で使用されているクラスを返して、候補者をロードします。 * @return The Factory Class */ Protected Class <?> }ここで私は私たちの古い知り合いであるSpringFactoryiesLoaderに会いました。SpringFactoryiesLoaderは、Meta -Inf/spring.Factoriesの下でEnableAutoconFigurationの構成を読み取り、除外とフィルタリングを実行して、組み立てる必要があるクラスを取得します。最後に、すべてのautoconfigurationimportlistenerをmeta-inf/spring.factories autoconfigurationimporteventイベントを実行すると、コードは次のとおりです。
private void fireautoconfigurationimportevents(list <string> configurations、set <string> excclusions){list <autoconfigurationimportlistener>リスナー= getautoconfigurationimportlisteners(); if(!riessers.isempty()){autoconfigurationimportevent event = new autoconfigurationimportevent(this、configurations、excclusions); for(autoconfigurationimportlistenerリスナー:リスナー){invokeawaremethods(リスナー); listener.onautoconfigurationimportevent(event); }}} protected list <autoconfigurationimportlistener> getautoconfigurationimportlisteners(){return springfactoriesloader.loadfactories(autoconfigurationimportlistener.class、this.beanclassoloader); }前のリンクでは、どのクラスを組み立てる必要があるかを判断するだけで、これらの自動化されたクラスはいつスプリングブートで処理されますか?簡単に分析しましょう。
2.1。 AbstractApplicationContextの更新方法:
この方法は決まり文句です。この方法に注意してください。
//コンテキストで豆として登録された工場プロセッサを呼び出します。 InvokeBeanFactoryPostProcessors(BeanFactory);
BeanFactoryPostProcessorのプロセスは次のとおりです。このインターフェイスBeanDefinitionRegistryPostProcessorをご覧ください。
/ * * Copyright 2002-2010元の著者または著者。 * * Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。 *ライセンスに準拠している場合を除き、このファイルを使用することはできません。 *ライセンスのコピーを取得することができます * * http://www.apache.org/licenses/license-2.0 * *該当する法律で要求されていない場合、または書面で合意しない限り、ライセンスに基づいて配布されるソフトウェア *は、保証または条件なしで「現状」に分配されます。 *権限を管理する特定の言語のライセンスと、ライセンスに基づく制限を参照してください。 */package org.springframework.beans.factory.support; import org.springframework.beans.beansexception; Import org.springframework.beans.factory.config.beanfactorypostprocessor;/** *標準{@link beanfactorypostprocesserのspiを拡大するために、Beanfactostrocessorの拡張を標準に及ぼします。 <i>before</i> regular * BeanFactoryPostProcessor detection kicks in. In particular, * BeanDefinitionRegistryPostProcessor may register further bean definitions * which in turn define BeanFactoryPostProcessor instances. * * @author Juergen Hoeller * @since 3.0.1 * @see org.springframework.context.annotation.ConfigurationClassPostProcessor */public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { /** * Modify the application context's internal bean definition registration after its * standard initialization. All regular bean definitions will have been loaded, * but no beans will have been instantiated yet. This allows for adding further * bean definitions before the next post-processing phase kicks in. * @param registry the bean definition registry used by the application context * @throws org.springframework.beans.BeansException in case of errors */ void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;}该接口继承了BeanFactoryPostProcessor。
2.2。 ConfigurationClassPostProcessor class
该类主要处理@Configuration注解的,它实现了BeanDefinitionRegistryPostProcessor, 那么也间接实现了BeanFactoryPostProcessor,关键代码如下:
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { int factoryId = System.identityHashCode(beanFactory); if (this.factoriesPostProcessed.contains(factoryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + beanFactory); } this.factoriesPostProcessed.add(factoryId); if (!this.registriesPostProcessed.contains(factoryId)) { // BeanDefinitionRegistryPostProcessor hook apparently not supported... // Simply call processConfigurationClasses lazily at this point then. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } enhanceConfigurationClasses(beanFactory); beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); }/** * Build and validate a configuration model based on the registry of * {@link Configuration} classes. */ public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { //.....省略部分代码// Parse each @Configuration class ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size()); do { parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<String>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty()); // ....省略部分代码}其实这里注释已经很清楚了,我们可以清楚的看到解析每一个@ConfigurationClass的关键类是:ConfigurationClassParser,那么我们继续看一看这个类的parse方法:
public void parse(Set<BeanDefinitionHolder> configCandidates) { this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>(); for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); } } processDeferredImportSelectors(); }在这里大家留意一下最后一句processDeferredImportSelectors方法,在这里将会对DeferredImportSelector进行处理,这样我们就和AutoConfigurationSelectImporter结合到一起了:
private void processDeferredImportSelectors() { List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors; this.deferredImportSelectors = null; Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR); for (DeferredImportSelectorHolder deferredImport : deferredImports) { ConfigurationClass configClass = deferredImport.getConfigurationClass(); try { String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata()); processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", ex); }}}请大家关注这句代码:String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());在这里deferredImport的类型为DeferredImportSelectorHolder:
private static class DeferredImportSelectorHolder { private final ConfigurationClass configurationClass; private final DeferredImportSelector importSelector; public DeferredImportSelectorHolder(ConfigurationClass configClass, DeferredImportSelector selector) { this.configurationClass = configClass; this.importSelector = selector; } public ConfigurationClass getConfigurationClass() { return this.configurationClass; } public DeferredImportSelector getImportSelector() { return this.importSelector; }}在这个内部类里持有了一个DeferredImportSelector的引用,至此将会执行自动装配的所有操作
1)自动装配还是利用了SpringFactoriesLoader来加载META-INF/spring.factoires文件里所有配置的EnableAutoConfgruation,它会经过exclude和filter等操作,最终确定要装配的类
2) 处理@Configuration的核心还是ConfigurationClassPostProcessor,这个类实现了BeanFactoryPostProcessor, 因此当AbstractApplicationContext执行refresh方法里的invokeBeanFactoryPostProcessors(beanFactory)方法时会执行自动装配
The above is the automatic assembly in SpringBoot introduced to you by the editor.それがあなたに役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は時間内に返信します!