オンラインの問題: FeignClient の循環依存関係とソース コード分析

1シーン再現

依存関係: 点線の左側が実装クラス、点線の右側が Spring のネイティブ インターフェイス クラスまたはアノテーションです。
通常、循環依存関係はありませんが、実際の動作では、「解決できない循環参照がありますか?」という例外メッセージが
循環依存関係の可能性があることを明確に示しており、例外ログからさらなる調査が必要です。
ここに画像の説明を挿入

1.1 偽クライアント

Feign を通じてサービスに電話します。
ここに画像の説明を挿入

1.2 ハンドラーインターセプター

新しいトークン インターセプターを作成します。
ここに画像の説明を挿入

1.3 WebMvcConfigurer

トークンインターセプターを追加します。
ここに画像の説明を挿入

1.4 コントローラー

インターフェイスは FeignClient に依存します。
ここに画像の説明を挿入

2つのオプション

TokenInterceptor の FeignClient に @Lazy を追加し、SpringBoot 起動時に TokenInterceptor の FeignClient をロードしないでください。サービス開始後、必要に応じて再度ロードされるため、開始時にシングルトンの FeignClient を繰り返し検証する必要がなくなります。サービスは正常に開始されます。
ここに画像の説明を挿入

3 分析

SpringBoot が起動すると、スタック情報は次のようになります。例外が内部から外部にスローされ、
多くの例外情報があり、セクションで確認できます。

  • 第一段落
    org.springframework.beans.factory.UnsatisfiedDependencyException: 'rpcApi' という名前の Bean の作成中にエラーが発生しました: フィールド 'feignTemplateService' を通じて表現される満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.UnsatisfiedDependencyException です: 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration' という名前の Bean の作成中にエラーが発生しました: メソッド 'setConfigurers' パラメータ 0 で表現された満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.UnsatisfiedDependencyException です: 'webMvcHandler' という名前の Bean の作成中にエラーが発生しました: フィールド 'tokenInterceptor' を通じて表現される満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.UnsatisfiedDependencyException です: 'tokenInterceptor' という名前の Bean の作成中にエラーが発生しました: 満たされていない依存関係はフィールド「templateService」を通じて表現されます。ネストされた例外は org.springframework.beans.factory.BeanCurrentlyInCreationException です: 'com.monkey.tutorial.common.rpc.IFeignTemplateService' という名前の Bean の作成中にエラーが発生しました: 要求された Bean は現在作成中です: 解決できない循環参照はありますか?

  • 第二段落
    原因: org.springframework.beans.factory.UnsatisfiedDependencyException: 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration' という名前の Bean 作成エラー: メソッド 'setConfigurers' パラメータ 0 を通じて表現された満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.UnsatisfiedDependencyException です: 'webMvcHandler' という名前の Bean の作成中にエラーが発生しました: フィールド 'tokenInterceptor' を通じて表現される満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.UnsatisfiedDependencyException です: 'tokenInterceptor' という名前の Bean の作成中にエラーが発生しました: フィールド 'templateService' を通じて表現される満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.BeanCurrentlyInCreationException: 'com.monkey.tutorial.common.rpc という名前の Bean の作成中にエラーが発生しました。

  • 第三段
    原因: org.springframework.beans.factory.UnsatisfiedDependencyException: 'webMvcHandler' という名前の Bean 作成エラー: フィールド 'tokenInterceptor' を通じて表現される満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.UnsatisfiedDependencyException です: 'tokenInterceptor' という名前の Bean の作成中にエラーが発生しました: フィールド 'templateService' を通じて表現される満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.BeanCurrentlyInCreationException です: 'com.monkey.tutorial.common.rpc.IFeignTemplateService' という名前の Bean の作成中にエラーが発生しました: 要求された Bean は現在作成中です: 解決できない循環参照はありますか?

  • 第 4 段目
    の原因: org.springframework.beans.factory.UnsatisfiedDependencyException: 'tokenInterceptor' という名前の Bean 作成エラー: フィールド 'templateService' を通じて表現される満たされていない依存関係。ネストされた例外は org.springframework.beans.factory.BeanCurrentlyInCreationException です: 'com.monkey.tutorial.common.rpc.IFeignTemplateService' という名前の Bean の作成中にエラーが発生しました: 要求された Bean は現在作成中です: 解決できない循環参照はありますか?

  • 第五段
    原因: org.springframework.beans.factory.BeanCurrentlyInCreationException: 'com.monkey.tutorial.common.rpc.IFeignTemplateService' という名前の Bean 作成エラー: 要求された Bean は現在作成中です: 解決できない循環参照はありますか?
    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355) ~[spring-beans-5.3.6.jar:5.3.6] で

3.1 位置決め異常

例外情報の5 番目の段落から、例外がスローされる場所を見つけることができます:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation。
このメソッドはシングルトン オブジェクトを作成する前の検証です。ソース コードは次のとおりです。下図:
ここに画像の説明を挿入
ソースコードより シングルトンオブジェクトを作成する前に、beforeSingletonCreationを通して、作成するシングルトンオブジェクトが現在のコレクションにあるかどうかを確認します。ソースコードの判定ロジックにより、シングルトンオブジェクト名(beanName)であれば、 ) 作成されるものが singletonsCurrentlyInCreation にある場合、例外がスローされます。

3.2 デバッグスキーム

例外の場所とスローされた例外の論理分析を通じて、
ブレークポイントのデバッグは beforeSingletonCreation で中断できます。以下は、いくつかのコアの場所 (rpcApi、WebMvcHandler、TokenInterceptor、および IFeignTemplateService) のデバッグ情報です。

3.2.1 rpcApi

rpcApi 検証作成シングルトン オブジェクトのデバッグ情報を次の図に示します。
図の右側では、this.singletonsCurrentlyInCreation コレクションが空であるため、検証に合格できます。
ここに画像の説明を挿入

3.2.2 IFeignTemplateService

rpcApi は IFeignTemplateService に依存しているため、
IFeignTemplateService 検証を入力します。そのため、rpcApi 検証が完了すると、IFeignTemplateService 検証に入ります。デバッグ結果は
次の図に示されています。図からわかるように、IFeignTemplateService の this.singletonsCurrentlyInCreation にはすでに要素 rpcApi、
つまり rpcApi は IFeignTemplateService に依存しており、IFeignTemplateService はコレクション singletonsCurrentlyInCreation に含まれていないため、検証はパスされます。

ここに画像の説明を挿入

3.2.3 mvcリソースプロバイダー

次に、検証のステップが mvcResourceUrlProvider によってインターセプトされ、
mvcResourceUrlProvider の検証が最初に実行されます。
デバッグ結果は次の図に示されています。図からわかるように、rpcApi と IFeignTemplateService は既に this.singletonsCurrentlyInCreation に存在しており
、 rpcApiと IFeignTemplateService は mvcResourceUrlProvder に依存していることを確認します。この時点で、検証は合格します。
ここでの核心は、IFeignTemplateService が this.singletonsCurrentlyInCreation に追加されており、後続の例外スローの導入です
ここに画像の説明を挿入

3.2.4 webMvcHandler

mvcResourceUrlProvider は webMvcHandler に依存しています。mvcResourceUrlProvider
が検証をパスすると、webMvcHandler の検証に入ります。
デバッグ結果は次の図に示されています。図からわかるように、webMvcHandler は例外なく検証をパスしました。
ここに画像の説明を挿入

3.2.5 トークンインターセプター

webMvcHandler は tokenInterceptor に依存しており、webMvcHandler の検証後、tokenInterceptori の検証に入ります。tokenInterceptor の
検証プロセスは下図のようになり、検証が通過します。
ここに画像の説明を挿入

3.2.6 IFeignTemplateService

tokenInterceptor も IFeignTemplateService に依存しているため、
tokenInterceptor が検証された後、IFeignTemplateService の検証が継続されます。
デバッグ プロセスは次の図に示されています。上記の分析に基づいて、IFeignTemplateService は既に this.singletonsCurrentlyInCreation に存在します (IFeignTemplateService は mvcResourceUrlProvider に依存しているため
、 mvcResourceUrlProvider は webMvcHandler に依存します)
検証が失敗し、例外がスローされます。
ここに画像の説明を挿入
例外をスローする
ここに画像の説明を挿入

3.3 循環依存関係

分析後、形成された循環依存関係が次の図に示されます。

ここに画像の説明を挿入

3.4 解決する

SpringBootサービスを確実に動作させるためには循環依存関係を解消する必要があるため、
TokenInterceptorではサービス起動時にFeignClieitをロードせず、
FeignClientに@Lazyアノテーションを付与してロードを遅延させています。開始すると、呼び出しがあるときにロードされます。
ここに画像の説明を挿入

4 まとめ

(1) 循環依存関係には、A->B->C->A などの明示的な依存関係と、段階的にデバッグする必要がある暗黙的な依存関係があります。(2) 循環依存関係の解決策: ループを中断し、コード設計を調整します
。 、読み込み遅延など。

おすすめ

転載: blog.csdn.net/Xin_101/article/details/130034641