@ConditionalOnMissingBeanコメントの春

Spring4は、現在の環境や状況に基づいて動的に注入Beanコンテナに@Conditionalコメント、便利なプログラムを立ち上げ、@Conditionalノートは春@Conditionalの友人に会場に精通していない学ぶためにこのブログの例をコメントして詳細に説明することができます。

@Conditionalノートに続いて、このコメントに基づいてすることは容易にこれまで以上に、このような@ ConditionalOnBean、@ ConditionalOnMissingBean、@ ConditionalOnExpression、@ ConditionalOnClass ......動的に注入豆など多くの派生のアノテーションを導入しました。この記事のお得な情報は@ConditionalOnBeanコメントを説明します。

2つの構成クラス豆コンピュータクラス、ノートブックコンピュータは、コンピュータはスペアであります。現在のBeanコンテナは、コンピュータを持っている場合、スタンバイコンピュータが注入されていない、そうでない場合、二次デバイスを注入、@ConditionalOnMissingBeanに使用する必要があります。

@Configuration
パブリッククラスBeanConfig {

@Bean(名= "NotebookPC")
パブリックコンピュータコンピュータ1(){
新新しいコンピュータ( "ラップトップ")を返す;
}

@ConditionalOnMissingBean(Computer.class)
@Bean( "reservePC")
公共のコンピュータコンピューター2( ){
新しい新しいコンピュータ(「バックアップコンピュータ」)を返す;
}
}
機能の実現にこの注釈を、この@ConditionalOnMissingBean私たちはすべてで何かをするために?私たちはよく見て..

それをチェックアウト:
まず、@ConditionalOnMissingBeanの文を見て:

//は、クラスやメソッドにマークすることができる
@Target({ElementType.TYPE、ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//使用@Conditionalアノテーション条件クラスOnBeanConditionある
@Conditional({OnBeanCondition.class })
パブリック@interface ConditionalOnMissingBean {
クラス[]の値(){<?>}デフォルト;

String []型タイプ(){}デフォルト;

<?>無視クラス[](){}デフォルト;

String []型ignoredType()デフォルト{};

クラス[]アノテーション(){}デフォルト<延び注釈?>;

文字列[]名(){}デフォルト;

SearchStrategy検索()デフォルトSearchStrategy.ALL;
}
この時点で、我々はおなじみ@Conditional参照ノート、クラスの条件としてOnBeanCondition。

OnBeanConditionクラスの宣言:

//ソート順序がアセンブリ注釈付き定義2147483647は、デフォルト値である
@Order(2147483647)
クラスOnBeanCondition SpringBootConditionを拡張実装ConfigurationCondition {
クラスSpringBootConditionを継承し、OnBeanConditionは、メソッドがクラスではない一致、クラスがSpringBootConditionの方法と一致し実施しています。詳細スプリングConfigurationConditionインターフェースへのインターフェースに精通していないOnBeanConditionも達成ConfigurationCondition、ConfigurationConditionリーダーインターフェイスを理解します。OnBeanConditionクラスは、注釈は、Beanの登録時に有効に示すためgetConfigurationPhase()メソッドをオーバーライドします。

ConfigurationPhase getConfigurationPhase公開(){
ConfigurationPhase.REGISTER_BEANを返す;
}
マッチ方法から始まります。

//メソッドのSpringBootConditionクラスと一致する
マッチ(ConditionContextコンテキスト、AnnotatedTypeMetadataメタデータ){パブリックブールファイナル
//は、(ポジショニングで示される)現在のクラス名やメソッド名を取得
文字列classOrMethodName = getClassOrMethodName(メタデータ);

試み{
//キーコード:ここで判定される結果
ConditionOutcome転帰this.getMatchOutcome =(コンテキストメタデータ);
//ログ格納さ
this.logOutcome(classOrMethodName、結果);
へ//レコード
this.recordEvaluation(文脈、classOrMethodName、結果) 。
//最後の戻りConditionOutcomeブール結果を返すisMatchある
;リターンoutcome.isMatch()
}キャッチ(NoClassDefFoundErrorがVAR5){
+ "が見つかりません+ var5.getMessage()「による」+ classOrMethodName +「の条件を評価できませんでした」(新IllegalStateExceptionがスロー。独自の構成は、そのクラスに依存しないことを確認してください。あなたが@ComponentScanningある場合、これがまた起こることができますspringframeworkパッケージ(例えば、あなたが誤ってデフォルトのパッケージに@ComponentScanを置く場合)」、VAR5)。
}キャッチ(のRuntimeException var6){
新しいIllegalStateExceptionがスロー( "のエラー処理状態を" + this.getName(メタデータ)、var6)。
}
}
关键代码在OnBeanCondition的getMatchOutcome方法上:

/ **
*決意の結果を得るための方法、ブール値の結果とConditionOutcomeクラスデポジット
* /
パブリックConditionOutcome getMatchOutcome(ConditionContextコンテキスト、AnnotatedTypeMetadataメタ){
//新しいConditionMessage返し
ConditionMessage matchMessage ConditionMessage.empty =()を;
OnBeanCondition。スペックBeanSearchSpec;
リストマッチング;
//これは、メタデータは、現在の注釈がConditionalOnMissingBeanマークされていないかを決定するためにisAnnotatedメソッドを呼び出しますです
//実際に@ ConditionalOnBean、@ ConditionalOnMissingBeanと@ConditionalOnSingleCandidateが判断をするので、ここでは、この条件のカテゴリを使用している
(metadata.isAnnotated場合(ConditionalOnBean.class.getName())){
スペック=新しい新しいOnBeanCondition.BeanSearchSpec(コンテキスト、メタデータ、ConditionalOnBean.class);
整合this.getMatchingBeans =(コンテキスト、スペック);
IF(matching.isEmpty()){
リターンConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnBean.class、新しいオブジェクト[] {}スペック)didNotFind( "任意の豆")atAll());
}

。matchMessage = matchMessage.andCondition(ConditionalOnBean.class、新しいオブジェクト[] {スペック})を求める( "豆"、 "豆")項目(Style.QUOTE、マッチング)。
}

IF(metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())){
OnBeanCondition.BeanSearchSpecスペック=新しいOnBeanCondition.SingleCandidateBeanSearchSpec(コンテキスト、メタデータ、ConditionalOnSingleCandidate.class)。
マッチング= this.getMatchingBeans(文脈、スペック)。
(matching.isEmpty()){もし
リターンConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class、新しいオブジェクト[] {仕様})。didNotFind( "任意の豆")。
}

IF(!This.hasSingleAutowireCandidate(context.getBeanFactory()、マッチング、spec.getStrategy()== SearchStrategy.ALL)){
リターンConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class、新しい新しいオブジェクト[] {}スペック) .didNotFind( "豆の豆からAプライマリ")項目(Style.QUOTE、マッチング));.
}

matchMessage = matchMessage.andCondition(ConditionalOnSingleCandidate.class、新しい新しいオブジェクト[] {} SPEC)豆から(「Aプライマリ豆を発見しました。 「).items(Style.QUOTE、マッチング);
}

//電流が注入されている場合ビーン@ConditionalOnMissingBean
IF(metadata.isAnnotated(ConditionalOnMissingBean.class.getName())){
//以下(スペックを返します)スペックは、このような検索戦略を検索する必要があるクラス名として、コンテンツの検索を提供してい......
=新しい新しいOnBeanCondition.BeanSearchSpecスペック(コンテキスト、メタデータ、ConditionalOnMissingBean.class);
この中で実装//メイン検索方法、および最後にリストを返し
整合this.getMatchingBeans =(コンテキスト、スペック);
//結果が決定探し出す
場合(!matching.isEmpty()){
リターンConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnMissingBean.class、新しい新しいオブジェクト[] {} SPEC)。( "豆"、 "豆"が見つかりました)。項目(Style.QUOTE、マッチング) );
}

matchMessage = matchMessage.andCondition(ConditionalOnMissingBean.class、新しい新しいオブジェクト[] {} SPEC)didNotFind( "任意の豆")atall(); ...
}

戻りConditionOutcome.match(matchMessage);
}
スペック=新しい新しいOnBeanCondition.BeanSearchSpec (コンテキスト、メタデータ、ConditionalOnBean.class)。

文は、内部クラスで取り出し@ConditionalOnMissingBean注釈から注釈に対応する属性:

BeanSearchSpec(ConditionContextコンテキスト、AnnotatedTypeMetadataメタデータ、クラスannotationType <?>){
this.annotationType = annotationType。
MultiValueMap <文字列オブジェクト>は、(真annotationType.getName())= metadata.getAllAnnotationAttributes属性。
//将属性がマップ这个中的数据放到对应的リスト成员变量中
this.collect(属性、 "名前"、this.names)。
this.collect(属性、 "値"、this.types)。
this.collect(属性、 "タイプ"、this.types)。
this.collect(属性、 "注釈"、this.annotations)。
this.collect(属性、 "無視"、this.ignoredTypes)。
this.collect(属性、 "ignoredType"、this.ignoredTypes)。
this.strategy =(SearchStrategy)メタデータ。
OnBeanCondition.BeanTypeDeductionException deductionException = NULL;

{試みる
(this.types.isEmpty()&& this.names.isEmpty()){場合
this.addDeducedBeanType(コンテキスト、メタデータ、this.types)。
}
}キャッチ(OnBeanCondition.BeanTypeDeductionException var7){
deductionException = var7。
}

this.validate(deductionException)。
}

//验证的方法
保護のボイドのvalidate(OnBeanCondition.BeanTypeDeductionException EX){
場合(!this.hasAtLeastOne(this.types、this.names、this.annotations)){
文字列メッセージ= this.annotationName()+ "指定されていませんでした「タイプ、名前や注釈を使用した豆。
(例== null)の場合は、{
新しいIllegalStateExceptionが(メッセージを)投げます。
} そうしないと {
新しい新しいIllegalStateExceptionをスロー(メッセージ+、EX「およびBeanのタイプので推定する試みでは、失敗しました」);
}
}
}
ルックgetMatchingBeans方法OnBeanConditionクラス、検索戦略に役立つ、検索戦略のプレゼンテーションを見ます

一覧プライベート<文字列> getMatchingBeans(ConditionContextコンテキスト、OnBeanCondition.BeanSearchSpecビーンズ){
//現在のマメ植物を得る
ConfigurableListableBeanFactory context.getBeanFactoryたBeanFactory =();
//現在の検索戦略は、ALLデフォルト、かどうかPARENTS ANCESTORS決定
IF(ビーンズ.getStrategy()== SearchStrategy.PARENTS beans.getStrategy ||()== SearchStrategy.ANCESTORS){
たBeanFactory親がbeanFactory.getParentBeanFactory =();
Assert.isInstanceOf(ConfigurableListableBeanFactory.class、親、 "SearchStrategy.PARENTSを使用することができません" );
//親やANCESTORS場合、工場出荷時の豆と現在の親植物
たBeanFactory =(ConfigurableListableBeanFactory)親;
}

IF(たBeanFactory == NULL){
リターンCollections.emptyList();
} {他
一覧<文字列> = beanNames新しい新しいのArrayList();
//現在の検索戦略をtrueにと、電流と等しい場合は
、ブールconsiderHierarchy beans.getStrategy =()= SearchStrategy.CURRENT ;!
//ここで豆の種類のタイプを見つける必要がある
//以下、特性が豆から見つける
イテレータvar6 = beans.getTypes()イテレータ();.

;文字列のbeanName
一方(var6.hasNext()){
のbeanName =(文字列)var6.nextを();
//型が見つかった場合、インスタンス名は、次のサンプルを見つけるための方法の名前は、実際に、豆の種類に応じて、下を見てgetNamesForTypeある
beanNames.addAll(this.getBeanNamesForType(たBeanFactory、のbeanName、context.getClassLoader()、considerHierarchy));
}

var6 = 。beans.getIgnoredTypes()イテレータ();

一方(var6.hasNext()){
のbeanName =(文字列)var6.next();
beanNames.removeAll(this.getBeanNamesForType(たBeanFactory、のbeanName、context.getClassLoader()、considerHierarchy))。
}

Var6 beans.getAnnotations =()イテレータ()。

(var6.hasNext()){一方
のbeanName =(文字列)var6.next();
beanNames.addAll(は、Arrays.asList(this.getBeanNamesForAnnotation(たBeanFactory、のbeanName、context.getClassLoader()、considerHierarchy)))。
}

Var6 beans.getNames =()イテレータ()。

(var6.hasNext()){一方
のbeanName =(文字列)var6.next();
(this.containsBean(たBeanFactory、のbeanName、considerHierarchy)){IF
beanNames.add(のbeanName)。
}
}
//女性将存放实例名的返回リスト
に戻るbeanNames。
}
}



//女性根据类型获取的名
プライベートコレクション<文字列> getBeanNamesForType(ListableBeanFactoryたBeanFactory、文字列型、クラスローダクラスローダ、ブールconsiderHierarchy)はないLinkageError {スロー
試し{
セット<文字列>結果=新しいLinkedHashSetのを();
this.collectBeanNamesForType(結果たBeanFactory、ClassUtils.forName(タイプ、クラスローダ)、considerHierarchy)。
結果を返します。
}キャッチ(ClassNotFoundExceptionがのvar6){
)(Collections.emptySetを返します。
}キャッチ(NoClassDefFoundErrorがvar7){
)(Collections.emptySetを返します。
}
}

プライベートボイドcollectBeanNamesForType(セットの<string>結果、ListableBeanFactoryたBeanFactory、クラス型、ブールconsiderHierarchy <?>){
result.addAll(BeanTypeRegistry.get(たBeanFactory).getNamesForType(タイプ))。
IF(considerHierarchy &&たBeanFactoryのinstanceof HierarchicalBeanFactory){
たBeanFactory親=((HierarchicalBeanFactory)たBeanFactory).getParentBeanFactory();
IF(instanceofのListableBeanFactory親){
this.collectBeanNamesForType(結果、(ListableBeanFactory)親、タイプ、considerHierarchy);
}
}

}
検索豆の完了後に、単にコードに戻って:

//電流が注入されている場合は豆@ConditionalOnMissingBean
IF(metadata.isAnnotated(ConditionalOnMissingBean.class.getName())){
//スペック(説明)、specはここで、このような検索方法として、コンテンツの検索を提供して戻り、我々は、検索する必要クラス名......
スペック=新しい新しいOnBeanCondition.BeanSearchSpec(コンテキスト、メタデータ、ConditionalOnMissingBean.class);
整合this.getMatchingBeans =(コンテキスト、スペック);
IF(!matching.isEmpty()){
戻りConditionOutcome.noMatch (ConditionMessage.forCondition(ConditionalOnMissingBean.class、新しい新しいオブジェクト[] {} SPEC)( "豆"、 "豆"が見つかりました)アイテム(Style.QUOTE、マッチング));
}

matchMessage = matchMessage.andCondition(ConditionalOnMissingBean.class、新しい新しいオブジェクト[] {} SPEC)didNotFind( "任意の豆")();. atall
}
リターンライン5リストが空でない場合は、オブジェクトを返しますConditionOutcome NOMATCH方法は、不一致を表しています。結果を格納するためのConditionOutcomeフィルタクラス、2つの変数のみ:

/ **
*結果に基づくフィルター
* /
publicクラスConditionOutcome {
/ **
*マッチング結果またはtrueにfalseに
* /
民間最終ブールの試合;
/ **
*マッチング結果情報
* /
プライベートConditionMessage最終メッセージ;
2つの違い:
@ConditionOnBeanでリストを判断した場合、リストに値がない場合、それは、そうでない場合は真偽を返します。

@ConditionOnMissingBean裁判官リスト、およびリストが値、trueを返しますを持っていない場合は、それ以外の場合はfalseを返し、他は同じロジックです

例:
@ConditionalOnBean(javax.sql.DataSource.class)    
Springコンテナまたはクラスのjavax.sql.DataSourceのすべての親血管の存在を必要とする少なくとも一つのインスタンス

 

おすすめ

転載: www.cnblogs.com/YuyuanNo1/p/12511121.html