フレームワーク知識照合
SpringBoot、SpringMVC、Spring とその機能の違いは何ですか?
- SpringBoot は、Spring アプリケーションの作成、操作、テスト、デプロイを簡素化するマイクロサービス フレームワークです。これにより、開発者は XML 構成にあまり注意を払う必要がなくなります。SpringMVC、Spring Security、Spring Data JPA などの多くのフレームワークを統合します。そしてビルトインTomcat
- SpringMVC は Web レイヤーの mvc フレームワークであり、応答要求の処理、フォーム パラメーターの取得、フォーム検証の実行などに使用されます。MVC デザイン パターンを実装する Java ベースのリクエスト駆動型軽量 Web フレームワークです.Model、View、Controller を分離することにより、Web レイヤーの責任を分離し、複雑な Web アプリケーションを論理的に明確な部分に分割します.開発を簡素化し、エラーを減らし、グループ内の開発者間の協力を促進します。
- Spring は、軽量の IoC および AOP コンテナー フレームワークです。これは、Java アプリケーションの基本的なサービスを提供するフレームワークのセットです。その目的は、エンタープライズ アプリケーションの開発を簡素化することです。これにより、開発者はビジネス ニーズだけを気にすることができます。一般的な構成方法には、XML ベースの構成、注釈ベースの構成、および Java ベースの構成の 3 つがあります。
Spring の IOC と AOP
IOC
IOC: Inversion of Control。従来、プログラム コードによって直接操作されていたオブジェクトの呼び出し権をコンテナーに移し、コンテナーを介してオブジェクト コンポーネントのアセンブリと管理を実装します。つまり、コンポーネント オブジェクトに対する制御の転送は、プログラム コード自体から外部コンテナーに転送されます。オブジェクトが依存する他のオブジェクトは、受動的に渡されます。最も直感的な表現は、IOC が new に行かずにオブジェクトの作成を許可することです。これは、Spring によって自動的に生成され、Java のリフレクション メカニズムを使用し、実行時に構成ファイルに従ってオブジェクトを動的に作成および管理し、オブジェクト メソッドを呼び出します。
- 役割: オブジェクトの作成と依存関係の維持を管理する; デカップリング、コンテナは特定のオブジェクトを維持する; クラスの生成プロセスをホストする.
- 利点: オブジェクト間の相互依存性は Ioc コンテナーによって管理され、オブジェクトの注入は IOC コンテナーによって完了されるため、アプリケーションの開発が大幅に簡素化されます。Ioc はファクトリのようなもので、オブジェクトを作成するためにファイルまたは注釈を構成するだけで済みます。オブジェクトの作成方法を考慮する必要はありません。
初期化プロセス: XML-"Resource-"BeanDefinition-"BeanFactory - Spring の IOC には、コンストラクター注入、セッター メソッド注入、およびアノテーションに基づく注入の 3 つの注入方法があります。
AOP
AOP: ロジックまたは責任 (トランザクション処理、ログ管理、権限制御など) をカプセル化できるアスペクト指向プログラミング。結合され、将来のスケーラビリティと保守性を助長します。AOPがない場合、何らかのログ管理を行っている場合は、各メソッドにログ処理を追加する必要があるかもしれません. ロジックを変更する必要がある場合は、1つずつ実行する必要があります. AOP の動的プロキシを介して、指定された場所で対応するプロセスを実行できます。このように、いくつかの横方向の機能を抽出して独立したモジュールを形成し、これらの機能を指定された位置に挿入することができます。この考え方は、アスペクト指向プログラミング (AOP) と呼ばれます。
- 動的プロキシ実装に基づいて、プロキシされるオブジェクトがインターフェースを実装する場合、Spring AOP は JDK 動的プロキシを使用してプロキシ オブジェクトを作成します。インターフェースを実装しないオブジェクトの場合、JDK 動的プロキシーは使用できず、CGlib 動的プロキシーを使用して、処理用のプロキシー・オブジェクトのサブクラスが生成されます。
- AspectJ も AOP フレームワークであり、静的プロキシの拡張です. いわゆる静的プロキシは、AOP フレームワークがコンパイル フェーズ中に AOP プロキシ クラスを生成することを意味するため、コンパイル時拡張とも呼ばれます. (アスペクト) コンパイル フェーズ中に Java に変換されます。バイトコードでは、実行時の拡張 AOP オブジェクトです。静的プロキシと動的プロキシの違いは、AOP プロキシ オブジェクトを生成するタイミングが異なり、1 つはコンパイル時、もう 1 つは実行時です。静的プロキシはパフォーマンスが向上しますが、処理には特定のコンパイラが必要です。
- AOP の動的プロキシ:
- JDK の動的プロキシは、インターフェイスのプロキシのみを提供し、クラスのプロキシはサポートしていません。コアの InvocationHandler インターフェイスと Proxy クラスである InvocationHandler は、invoke() メソッドのリフレクションを通じてターゲット クラスのコードを呼び出し、分野横断的なロジックとビジネスを動的に織り込みます。次に、Proxy は InvocationHandler を使用して、特定のインターフェイスに準拠するインスタンスを動的に作成し、ターゲット クラスのプロキシ オブジェクトを生成します。
- プロキシ クラスが InvocationHandler インターフェースを実装していない場合、Spring AOP は CGLib (コード生成ライブラリ) を使用してターゲット クラスを動的にプロキシすることを選択します。CGLib はコード生成用のクラス ライブラリであり、実行時に指定されたクラスのサブクラス オブジェクトを動的に生成し、特定のメソッドをオーバーライドし、拡張コードを追加して AOP を実現できます。CGLib は継承を使用する動的プロキシであるため、クラスが final としてマークされている場合、動的プロキシに CGLib を使用することはできません。
AOP の関連概念:
- アドバイス: アスペクトの目標を説明するために使用されます, つまり, アスペクトが完了しなければならない作業. アドバイスは、アスペクトが何であり、いつそれを使用するかを定義します. 事前通知、事後通知、復帰通知、例外通知、サラウンド通知の5種類があります。
- ポイントカット pointcut: アスペクトはアプリケーションのすべての接続ポイントを通知する必要はなく、ポイントカットはアスペクトが通知する接続ポイントの範囲を狭めるのに役立ちます。アドバイスがアスペクトのいつ、何を定義するかを定義する場合、ポイントカットはその場所を定義します。つまり、アドバイスを実行するために実行する必要がある接続ポイントを定義します。
- アスペクト アスペクト: 通知とポイントカットの組み合わせ、通知とポイントカットの組み合わせは、アスペクトの内容全体を定義します: それが何であるか、いつ、どこでその機能を完了するかです。
- 結合ポイント: アプリケーションの実行中にアスペクトを挿入できるポイント. このポイントは、メソッドが呼び出されたとき、例外がスローされたとき、またはフィールドが変更されたときです. アスペクト コードはこれらのポイントを使用して、アプリケーションのポリシー フローにプラグインし、新しい動作を追加します。
- はじめに: 新しいメソッドまたはプロパティを既存のクラスに追加できます。
- Weaving into Weaving: アスペクトをターゲット オブジェクトに適用し、新しいプロキシ オブジェクトを作成するプロセス。アスペクトは、指定された結合点でターゲット オブジェクトに織り込まれます。織り込むことができるターゲット オブジェクトのライフ サイクルには多くのポイントがあります。
- コンパイル時間: アスペクトは、ターゲット クラスがコンパイルされるときに織り込まれます。この方法には、特別なコンパイラが必要です。
- クラスのロード期間: 対象のクラスが JVM にロードされると、アスペクトが織り込まれます。このアプローチには、アプリケーションに取り込まれる前にターゲット クラスのバイトコードを強化する特別なクラス ローダーが必要です。
- ランタイム: アスペクトは、アプリケーションの実行中のある時点で織り込まれます。通常、アスペクトを織り込む場合、AOP コンテナはターゲット オブジェクトのプロキシ オブジェクトを動的に作成します。
依存性注入 (DI) とは
依存性注入 (DI) は、コンポーネント間の依存性が実行時にコンテナーによって決定されることを意味します。つまり、特定の依存性が同時にコンポーネントに動的に注入されます。依存性注入の目的は、コンポーネントの再利用の頻度を増やし、システムの柔軟で拡張可能なプラットフォームを構築し、クラスを分離することです。
IOC の重要なポイントの 1 つは、システム操作中に必要な他のオブジェクトをオブジェクトに動的に提供することです。これは、依存性注入によって実現されます。
例: ClassB のオブジェクト b を ClassA で使用する 通常、B のオブジェクトは A のコードに表示する必要があります。依存性注入技術を採用した後、A のコードはプライベート B オブジェクトを定義するだけで済み、このオブジェクトを取得するために直接 new する必要はありませんが、関連するコンテナー制御プログラムを使用して B のオブジェクトを外部から新しくし、それをA.引用します。
依存性注入と制御の逆転の違いは次のとおりです。依存性注入はより実装に傾いていますが、制御の逆転は法則に傾いています。
- 制御の反転: オブジェクト インスタンスを作成する制御権は、コード制御から IOC コンテナー制御に剥奪されます。
- 依存性注入: オブジェクト インスタンスが作成されると、オブジェクトにプロパティ値または他のオブジェクト実装が注入されます。
注入方法
コンストラクター注入、フィールド注入
春の豆の範囲
スコープは、Spring Bean のスコープを定義します.Spring 構成ファイルで Bean を定義する場合、スコープ構成項目を宣言することで、Bean のスコープを柔軟に定義できます。
- singleton (singleton): 唯一の Bean インスタンス。IOC は Bean のみを作成して返します。Spring の Bean はデフォルトでシングルトンです。
- プロトタイプ (プロトタイプ): 各リクエストは新しい Bean インスタンスを作成します。
- request: HTTP 要求のみが作成されます。各要求は新しい Bean を作成します。Bean は現在の HTTP 要求でのみ有効であり、WebApplicationContext 環境に適用されます。
- セッション: HTTP リクエストのみが作成され、各リクエストは新しい Bean を作成します。Bean は現在の HTTP セッション内でのみ有効です。
- global-session: グローバル セッション スコープ。Spring5 では使用できません。
Spring でのシングルトン Bean のスレッド セーフの問題
シングルトン Bean にはスレッド セーフの問題があります。複数のスレッドが現在同じオブジェクトで動作している場合、オブジェクトの非静的メンバー変数を書き込むときにスレッド セーフの問題が発生します。
解決:
- Bean のスコープをプロトタイプに変更します。クラスまたはインターフェースに @Scope("prototype") を追加し、インターフェースが呼び出されるたびに新しい Bean が生成されることを示します。
- クラスで TreadLocal メンバー変数を定義し、安全でない変数のメンバー変数を ThreadLocal に保存します。TreadLocal は、各スレッドが変数の独立したコピーを提供することを意味します。これにより、各スレッドが変数の独自のコピーを持っているため、複数のスレッドがアクセスするデータの競合から分離されます。
春の Bean のライフ サイクル
-
Bean のインスタンス化: Spring が起動し、Spring で管理する必要がある Bean を見つけてロードし、Bean をインスタンス化します。
- BeanFactory コンテナーの場合、クライアントがコンテナーから初期化されていない Bean を要求した場合、または Bean の初期化時に初期化されていない別の依存関係を注入する必要がある場合、コンテナーはインスタンス化のために createBean を呼び出します。
- ApplicationContext コンテナーの場合、コンテナーの開始時にすべての Bean がインスタンス化されます。
- コンテナーは BeanDefinition オブジェクト内の情報を取得することでインスタンス化されますが、これは単なるインスタンス化であり、依存性注入は完了しません。インスタンス化された Bean は BeanWrapper でラップされ、BeanWrapper はオブジェクト プロパティを設定するためのインターフェイスを提供するため、プロパティを設定するためのリフレクション メカニズムの使用を回避します。
-
Bean プロパティの設定: Bean がインスタンス化された後、Bean の紹介と値が Bean のプロパティに注入されます。Spring は、BeanDefinition の情報と BeanWrapper が提供する設定プロパティ インターフェイスに従って、依存性注入を実行します。
-
Inject the Aware interface : オブジェクトが xxxAware インターフェイスを実装しているかどうかを検出し、関連するインターフェイスを Bean に注入します。
- Bean が BeanNameAware インターフェースを実装する場合、Spring は Bean の ID を setBeanName() メソッドに渡します。
- Bean が BeanFactoryAware インターフェースを実装する場合、Spring は setBeanFactory() メソッドを呼び出して BeanFactory コンテナー インスタンスを渡します。
- Bean が ApplicationContextAware インターフェースを実装する場合、Spring は Bean の setApplicationContext() メソッドを呼び出して、Bean のアプリケーション コンテキスト参照を渡します。
-
カスタム処理の実行: 上記の手順の後、Bean は正しく構築されました.オブジェクトを使用する前にカスタム処理を追加する場合は、BeanPostProcessor インターフェイスを介して実装します。
- postProcessBeforeInitialzation( Object bean, String beanName ) 現在初期化されている Bean オブジェクトが渡され、この Bean で任意の処理を実行できます。この関数は InitialzationBean の前に実行されるため、前処理と呼ばれます。このステップでは、すべての Aware インターフェイスの注入が行われます。
- postProcessAfterInitialzation( Object bean, String beanName ) 現在初期化されている Bean オブジェクトが渡され、この Bean で任意の処理を実行できます。この関数は、InitialzationBean が完了した後に実行されるため、後処理と呼ばれます。
-
InitializingBean と init メソッド
- Bean が InitializingBean インターフェースを実装する場合、Spring はその afterPropertiesSet() メソッドを呼び出します。同様に、Bean が init-method を使用して初期化メソッドを宣言すると、このメソッドも呼び出されます。クライアントコードの侵入を減らすために、Spring は Bean 構成に init-method 属性を提供します。この属性は、この段階で実行する必要がある関数の名前を指定します。Spring は、初期化フェーズで設定した関数を実行します。init-method は基本的に InitializingBean インターフェースを引き続き使用します。(これらのメソッドはオーバーライドできます)
-
DisposableBeanとdestroy-method
- Init メソッドと同様に、destroy メソッドに関数を指定することで、Bean が破棄される前に指定したロジックを実行できます。(これらのメソッドはオーバーライドできます)
Spring フレームワークで使用される設計パターン
- ファクトリ モード: BeanFactory と ApplicationContext を介して Bean オブジェクトを作成します。
- プロキシ モード: Spring AOP の実装。
- シングルトン モード: Spring の Bean はデフォルトでシングルトンです。
- 新しく生成されたインスタンスの消費を減らす: Spring はリフレクションまたは CGLIB 動的プロキシを介して Bean を生成します。これは非常にパフォーマンスを消費する操作であり、オブジェクトへのメモリの割り当てにも複雑なアルゴリズムが必要です。
- jvm ガベージ コレクションの削減: Bean インスタンスはリクエストごとに新しく生成されないため、自然にリサイクルされるオブジェクトは少なくなります。
- シングルトン取得 Bean 操作の最初の世代を除いて、残りはキャッシュから取得されます。
- テンプレート メソッド モード: jdbcTemplate、hibernateTemplate、およびデータベースで動作する Spring の Template で終わるその他のクラス。
- オブザーバー モード: 1 対多の依存関係を表示するようにオブジェクトを定義します. オブジェクトの状態が変化すると、それに依存するすべてのオブジェクトが通知され、更新されます (Spring のリスナーの実装 – ApplicationListener など)。春のイベントモデル。
- アダプター モード: Spring AOP の拡張機能またはアドバイス (アドバイス) はアダプター モードを使用し、Spring MVC もアダプター モードを使用してコントローラーを適応させます。
春の取引
トランザクション: この一連の操作を構成する論理ユニットが一緒に成功するか、一緒に失敗する操作の論理セット。
取引管理
- プログラムによるトランザクション: コードに TransactionTemplate をハードコードする (非推奨)
- 宣言型トランザクション: 構成ファイルで構成され、XML ベースの宣言型トランザクションと注釈ベースの宣言型トランザクションに分けられます。これは AOP に基づいており、基本的には AOP 関数によってメソッドの前後のメソッドをインターセプトし、インターセプトされたメソッドにトランザクション処理の機能を織り込みます。つまり、対象メソッドの開始前にトランザクションに参加し、対象メソッドの実行後に実行状況に応じてトランザクションをコミットまたはロールバックします。宣言型トランザクションの最大の利点は、ビジネス ロジック コードにトランザクション管理コードを混在させる必要がないことです. 構成ファイルで関連する構成を作成するか、@Transactional アノテーションを渡すだけで、トランザクション ルールをビジネス ロジックに適用できます. 唯一の欠点は、プログラムによるトランザクションのようなコード ブロックのレベルではなく、最も細かい粒度がメソッド レベルにしか到達できないことです。
トランザクションの伝播
複数のトランザクションが同時に存在する場合、Spring はこれらのトランザクションの動作をどのように処理しますか?
- PROPAGETION_REQUIRED: 現在のトランザクションがない場合は新しいトランザクションを作成し、トランザクションがある場合はトランザクションに参加します。が最も一般的な設定です。
- PROPAGATION_SUPPORTS: 現在のトランザクションをサポートし、現在トランザクションがある場合はトランザクションに参加し、現在トランザクションがない場合は非トランザクションとして実行します。
- PROPAGATION_MANDATORY: 現在のトランザクションをサポートします. トランザクションがある場合, トランザクションに参加します. トランザクションがない場合, 例外がスローされます.
- PROPAGATION_REQUIRES_NEW: 新しいトランザクションを作成します。現在トランザクションがあるかどうかに関係なく、新しいトランザクションを作成します。
- PROPAGATION_NOT_SUPPORTED: 非トランザクション方式で操作を実行します.現在のトランザクションがある場合は、現在のトランザクションを一時停止します.
- PROPAGATION_NEVER: 非トランザクション方式で実行し、トランザクションが現在存在する場合は例外をスローします。
- PROPAGATION_NESTED: 現在のトランザクションがある場合、ネストされたトランザクション内で実行します。現在トランザクションがない場合は、REQUIRED 属性に従って実行します。
Spring の通知メカニズム
- アドバイスの前(アドバイスの前): ジョイン ポイントの前に実行されるアドバイスですが、このアドバイスはジョイン ポイントの前の実行を防ぐことはできません (例外がスローされない限り)。
- アドバイスを返した後: ジョインポイントが正常に完了した後に実行されるアドバイス: たとえば、メソッドは例外をスローせずに正常に戻ります。
- アドバイスをスローした後(アドバイスをスローした後): メソッドが例外をスローして終了したときに実行されるアドバイス。
- After (finally) advice: ジョインポイントが (正常または異常に) 終了したときに実行されるアドバイス。
- 周りのアドバイス: メソッド呼び出しなど、ジョインポイントを囲むアドバイス。これは最も強力なタイプの通知です。サラウンド アドバイスは、メソッド呼び出しの前後でカスタム動作を実現できます。また、ジョイン ポイントの実行を継続するか、独自の戻り値を直接返すか、例外をスローして実行を終了するかを選択します。サラウンド通知は、最も一般的に使用されるタイプの通知です。Nanning や JBoss4 などの傍受ベースの AOP フレームワークのほとんどは、サラウンド アドバイスのみを提供します。
Spring の 3 レベルのキャッシュと循環依存関係
Spring の起動プロセスでは、3 レベル キャッシュと呼ばれる 3 つのマップが使用されます。
- singletonObjects: レベル 1 キャッシュ
- EarlySingletonObjects: 二次キャッシュ
- singletonFactory: L3 キャッシュ
Spring の起動プロセス
- 構成ファイルのロード
- 構成ファイルを解析し、beanDefination を変換して、Bean の初期化などに使用されるすべてのプロパティ、依存関係、およびさまざまなプロセッサを取得します。
- beanFactory を作成し、すべてのシングルトン Bean を初期化します
- すべてのシングルトン Bean を登録し、使用可能なコンテナー (通常は拡張された applicationContext) を返します
L1 キャッシュ
起動プロセスの 3 番目のステップ (beanFactory の作成とすべてのシングルトン Bean の初期化) では、初期化が完了した後、すべてのシングルトン Bean が Map (singletonObjects) に格納されます。beanName がキーで、シングルトン Bean が値です。これは一次キャッシュです
3 番目のステップでは、シングルトン Bean の初期化のプロセスは次のとおりです。
-
Bean は作成済みとしてマークされます
-
新しい Bean オブジェクト
-
循環依存がサポートされている場合、3 レベルのキャッシュを生成でき、Bean を事前に公開できます
-
プロパティの依存関係を解決するために Bean プロパティを設定する
-
Bean を初期化し、Aware インターフェイスを処理し、さまざまな Bean ポストプロセッサを実行し、初期化メソッドを実行し、必要に応じて aop プロキシ オブジェクトを生成します。
-
以前に aop の循環依存が解決された場合は、事前に生成されたプロキシ オブジェクトがキャッシュに配置され、その後、元の Bean を使用して初期化が続行されるため、最終的な戻り値を返す前に、元の Bean をプロキシ オブジェクトに置き換える必要があります。豆。
-
この時点で、Bean を使用できるようになり、Bean を登録し、破棄メソッドを登録します。
-
Bean をコンテナ (一次キャッシュ) に入れ、作成マークと二次および三次キャッシュを削除します
循環依存の問題
A を初期化すると、A が B に依存している、つまり、A は 2 番目のステップに初期化されており、この時点で B は初期化されていないため、A を一時停止して B を初期化する必要があることが判明したとします。今回は、A (作成中) をマークできるマップが必要です. 作成中の公開された Bean は、他の Bean 依存関係で使用できます. A が依存する Bean B を初期化するときに、B も A の依存関係を注入する必要があることがわかった場合、B は、作成されている beanMap から A (作成中) オブジェクトを直接取得して注入し、B の初期化を完了することができます。 、作成されている Bean に戻り、属性を注入し、最後に A も初期化されます。
構成で循環依存が許可されていない場合、上記のキャッシュは使用されません。一般的に言えば、複雑なビジネスの場合、たとえば、サービスを他のサービスに注入する必要があり、サービスが相互に参照するため、循環依存関係が発生します。したがって、循環依存関係がある場合は解決され、表示されない場合は解決されません。循環依存関係はサポートされていますが、初期オブジェクトは循環依存関係が発生した場合にのみ公開されます。それ以外の場合は、1 つだけです。 Bean を取得するメソッドは公開されていますが、Bean は実際には公開されていないため、このメソッドは実行されません。このブロックの実装は、1 つの Bean ファクトリのみをキャッシュする 3 レベルのキャッシュです。
この Bean ファクトリは、初期の Bean だけでなくプロキシ Bean も公開できます. aop プロキシがある場合は、元の Bean ではなくプロキシ オブジェクトに依存する必要があります。
L2 キャッシュ
第 3 レベルのキャッシュで言及されている循環依存は解決することしかできません。公開されたファクトリではなくオブジェクトであるため、新しいキャッシュを使用して公開された初期オブジェクト (earlySingletonObjects) を保存すると同時に、事前に公開されたファクトリを削除する必要があります。複数の循環依存関係がある場合、毎回 getObject を実行する必要はありません。
Spring Bean の自動アセンブリ
Spring のオブジェクトは、関連する他のオブジェクトを検索または作成する必要はなく、コンテナーは、相互に連携する必要があるオブジェクト参照を各オブジェクトに割り当てる役割を果たします。
- xml ベース
- no: デフォルトの方法は自動アセンブリを実行しないことであり、Bean は ref 属性を手動で設定することによってアセンブルされ、Bean の依存関係は property 要素を介して定義する必要があります
- byName: 属性名に従って自動でアセンブルします。BeanFactory はコンテナ内のすべての Bean を検索し、id が属性の setter メソッドの入力パラメータと一致する Bean を見つけます。
- byType: プロパティのデータ型に基づく自動アセンブリを示します。BeanFactory はコンテナー内のすべての Bean を検索します。
- 依存関係プロパティと同じタイプの Bean が存在する場合、プロパティは自動配線されます。
- そのような Bean が複数ある場合、Spring はどの Bean を注入するかを決定できず、UnsatisfiedDependencyException をスローします。
- 一致する Bean がない場合、何も起こらず、プロパティは設定されません。
- コンストラクター: 構築メソッドを使用して、オブジェクトの注入を完了します. 実際には、オブジェクトの検索は、構築メソッドのパラメーターの型に従って実行されます。これは、byType メソッドを使用することと同等です. つまり、Spring はパラメーターと同じデータ型の Bean を探し、コンストラクターを介してそれを注入します。
- default: 上位ラベルの自動アセンブリの値がデフォルトで採用されることを示します。複数の構成ファイルがある場合、各構成ファイルの自動アセンブリ方法は独立しています。
- アノテーション @Autowired に基づく
- @Autowired アノテーションを使用する前に、Spring 構成ファイル <context:annotation-config /> で構成する必要があります。
- Spring を起動すると、コンテナーは AutowiredAnnotationBeanPostProcessor ポスト プロセッサに自動的にインストールされ、コンテナーが @Autowired、@Resource、または @Inject をスキャンすると、IOC コンテナーで必要な Bean が自動的に検出され、オブジェクト プロパティにアセンブルされます。
- @Autowired を使用すると、最初にコンテナー内の対応するタイプの Bean が照会されます (タイプは Bean クラスで、名前は Bean id です)。
- クエリ結果が 1 つだけの場合、Bean はアセンブルされます。
- 複数のクエリ結果がある場合、@Autowired は名前で検索します。
- 見つからない場合、例外がスローされます。解決策は @Autowired(required = false) です。
- @Autowired は、コンストラクター、メンバー変数、およびセッター メソッドで使用できます。開発中のサービスまたはマッパーインターフェースでも使用されます
@Autowired と @Resource の違いに注意してください
- @Autowired はデフォルトで型アセンブリに従って注入され、複数の結果がクエリされた場合、それらは名前で検索されます。デフォルトでは、依存オブジェクトが存在する必要があります (required プロパティを false に設定できます)。
- @Resource はデフォルトで名前によってアセンブルおよび注入され、名前に一致する Bean が見つからない場合にのみ、タイプ別にアセンブルおよび注入されます。
@Component と @Bean の違い
アクションの対象が異なります。@Component はクラスに作用し、@Bean はメソッドに作用します。
-
@Component アノテーションは通常、クラスパス スキャンによって自動検出され、Spring コンテナーに自動アセンブルされます ( @ComponentScan アノテーションを使用して、スキャンするパスを定義できます)。
-
@Bean アノテーションは通常、アノテーションでマークされたメソッドで Bean を定義し、これが特定のクラスのインスタンスであることを Spring に伝え、使用する必要があるときにそれを返します。@Bean アノテーションは @Component アノテーションよりもカスタマイズ可能であり、多くの場所では @Bean アノテーションを介してのみ Bean を登録できます。たとえば、サードパーティ ライブラリを参照するクラスを Spring コンテナーにアセンブルする必要がある場合、それは @Bean アノテーションを介してのみ実現できます。
例えば
@Configuration public class AppConfig { @Bean public TransferService transferService() { return new TransferServiceImpl(); } }
に相当
<beans> <bean id="transferService" class="com.hty.TransferServiceImpl"/> </beans>
メソッド内にswitch文があり、その中で他のメソッドを呼び出す場合、@Componentでは実現できません。
クラスをSpring Beanとして宣言するための注釈は何ですか
通常、@Autowired アノテーションは Bean の自動アセンブルに使用され、クラスを @Autowired アノテーションで自動アセンブルできる Bean として識別したい場合は、次のアノテーションを使用できます。
- @Component: 一般に、任意のクラスを Spring Bean としてマークできます. クラスがどのレイヤーに属しているかがわからない場合は、 @Component アノテーションを使用してマークできます. @Component は、通常、さまざまなコンポーネントで使用されます。
- @Repository: DAO レイヤーに対応し、主にデータベース関連の操作に使用されます。
- @Service: 主にいくつかの複雑なビジネス ロジックを含み、DAO レイヤーの使用を必要とするサービス レイヤーに対応します。
- @Controller: Spring MVC のコントロール層に対応し、主にユーザーのリクエストを受け付けたり、サービス層のメソッドを呼び出してフロントエンドページにデータを返したりするために使用されます。
- @Configuration: XML を置き換えるために使用される構成クラスとしてクラスに注釈を付けます。
@必須和@修飾子
@Required: Bean 定義の表示プロパティ値または自動アセンブリを使用して、構成時に Bean のプロパティを構成する必要があることを示します。そうでない場合は、例外 BeanInitializationException がスローされます。
@Qualifier: サービスをコントローラーに注入する必要があります. サービスに複数の実装クラスがある場合、2 つの impl を区別する方法は、このアノテーションを使用して示すだけです.
※SpringMVCの実行手順
- ユーザーは、フロント コントローラーの DispatcherServlet にリクエストを送信します。
- DispatcherServlet は、リクエストを受信した後、HandlerMapping プロセッサ マッパーを呼び出して Handler をリクエストします。
- HandlerMapping は、リクエスト URL に従って特定のプロセッサを見つけ、プロセッサ オブジェクトとプロセッサ インターセプター (存在する場合) を生成し、それらを DispatcherServlet に返します。
- DispathcerServlet は HandlerAdapter プロセッサ アダプタを呼び出します。
- HandlerAdapter は、適応後の実行のために特定の Handler (Controller) を呼び出し、実行が完了した後、Handler は ModelAndView を DispatcherServlet に返します。
- DispatcherServlet は、解決のために ModelAndView を ViewResolver に渡します。
- ViewResolver は、解析後に特定の View を DispatcherServlet に返します。
- DispatcherServlet はビューをレンダリング (モデル データをビューに入力) してから、ユーザーに応答します。
SpringMVC の主要コンポーネント
- フロント コントローラ DispatcherServlet: リクエストを受け取り、結果に応答します。トランスポンダ相当
- プロセッサ マッパー HandlerMapping: 要求された URL に従ってハンドラーを検索します。
- プロセッサ アダプタ HandlerAdapter: Handler の実行を担当
- ビュー リゾルバ ViewResolver: ビューを解決し、ビューの論理名に従って実際のビューに解決します。
- ビュー ビュー (JSP、Thymeleaf)
SpringMVC はどのような問題を解決しますか
SpringMVC は MVC ベースのフレームワークで、主にフロントエンド ページとバックグラウンド コードの分離の問題を解決し、1 つのリクエストが 1 つのメソッドに対応します。
SpringMVC のリダイレクトと転送はどのように行われ、文字化けはどのように解決されるのでしょうか?
Forward: 戻り値の前に forward を追加します
リダイレクト: 戻り値の前にリダイレクトを追加します
POST: CharacterEncodingFilter フィルターを構成し、utf-8 に設定します。
GET: tomcat 構成ファイルを変更して、エンジニアリング エンコーディングと一致するエンコーディングを追加します。
SpringMVC のコントローラーはシングルトンですか? 何が問題ですか?の解き方?
これはシングルトンであり、マルチスレッドではスレッド セーフの問題が発生します。コントローラーに同期ロジックを直接記述しないでください。ただし、特定のサービスに記述し、コントローラー レイヤーにフィールドを記述しないでください。
SpringMVC 開発の共通アノテーション
@RequestMapping: リクエスト URL マッピングを処理するためのアノテーションで、クラスまたはメソッドで使用できます。クラスで使用すると、クラス内のすべての応答リクエスト メソッドがこのアドレスを親パスとして使用することを意味します。
- 値: 要求の実際のアドレスを示します。たとえば、値 = "/list" です。配列の形式であれば、複数のリクエストが 1 つのメソッドにマッピングされていることを意味します。正規表現の形式にすることもできます。
- method: GET、POST、DELETE、PUT など、リクエストのメソッド タイプを示します。
- params: このメソッドで処理する前に、要求アドレスに特定のパラメーター値が含まれている必要があることを指定します。複数の値を持つことができ、NAND OR 演算をサポートします。
- consumer: application/json、text/html など、リクエストを処理するために送信されたコンテンツ タイプ (Content-Type) を指定します。
- プロデュース: 返されるコンテンツ タイプを指定します。これは、要求ヘッダーの Accept タイプに指定されたタイプが含まれている場合にのみ返されます。
- headers: メソッドがリクエストを処理するために、リクエストに特定の指定されたヘッダー値が含まれている必要があることを指定します。
@PathVariable: URL のプレースホルダー パラメーターをメソッドのパラメーターにバインドします。たとえば、 @RequestMapping("show5/{id}/{name}") はこのアノテーションで取得できます。
@RequestParam: URL 内の次のパラメーターをメソッドのパラメーターにバインドします。たとえば、url: localhost:8080/hty?name=hty は、このアノテーションを使用して取得できます。背後にパラメーターがあるかどうかわからない場合、 required = false を追加できます。
@RequestBody: メソッド パラメーターの HTTP 要求を受け入れる JSON データを実装します。@PostMapping にのみ使用できます
@ResponseBody: コントローラー メソッド オブジェクトをフロント エンドへの json オブジェクト レスポンスに変換します
@RestController: @ResponseBody + @Controller、つまり、すべてのメソッドがデフォルトで json を返す
@GetMapping: メソッドによって返される対応するリクエストは、同じように GET、POST、DELETE、PUT です (use less)
SpringBoot の循環依存関係
循環依存とは何ですか?
Bean A 依赖 B,Bean B 依赖 A这种情况下出现循环依赖,即Bean A → Bean B → Bean A。
更复杂的间接依赖造成的循环依赖如下:Bean A → Bean B → Bean C → Bean D → Bean E → Bean A。当存在该依赖的时候,Spring加载Bean时无法决定先创建哪个Bean而产生异常。
の解き方
- コードのリファクタリングを行う
- 構成ファイルで相互に依存する 2 つの Bean のいずれかに lazy-init 属性を追加します。
- 注入された Bean の @Autowire アノテーションの後に @Lazy アノテーションを追加します
- Setter/Field インジェクションを使用する (Bean A の setterB に @Autowired を追加)
- 使用@PostConstruct
- L3 キャッシュ:
- AはdoGetBean、query cache、createBeanを実行してインスタンスを作成し、インスタンス化が完了すると、3層キャッシュsingleFactoriesに入れ、populateBeanメソッドを実行して属性を組み立てますが、属性があることがわかったときに、B のオブジェクト
- このとき、BのdoGetBean、query cache、createBeanを呼び出してインスタンスを作成し、インスタンス化完了後、3段キャッシュsingleFactoriesに配置し、populateBeanのアセンブリ属性を実行するが、このとき見つかった属性がAのオブジェクトがあること。
- このとき doGetBean を呼び出して A のインスタンスを作成しますが、getSingleton を実行してキャッシュをクエリすると、A のインスタンスは第 3 レベルのキャッシュからクエリされ、直接 A に返されます。この時点で、B は完全な属性のアセンブリであり、この時点で完全な B オブジェクトが配置され、singletonObjects にキャッシュされます。
- B が作成され、A が属性アセンブリを自然に完成させ、それも作成されて第 1 レベルのキャッシュに入れられます singletonObjects
MyBatisのメリット
- コードの量を減らして、簡単に始めましょう。
- アプリケーション プログラムやデータベースの既存の設計に影響を与えることはありません. SQL は XML で記述されているため、プログラム コードから完全に分離されており、結合度が低くなります。
- XML タグを提供し、動的 SQL ステートメントの作成をサポートします。
- オブジェクトとデータベース間の ORM フィールド関係マッピングをサポートするマッピング タグを提供します。
MyBatis の #{} と ${} の違いは何ですか?
- #{} はプリコンパイル処理、${} は文字列置換です。
- Mybatis が #{} を処理するとき、SQL の #{} を ? 記号に置き換え、PreparedStatement の set メソッドを呼び出して値を割り当てます。
- Mybatis が処理中の場合、{} を入れて、、 {} を変数の値に置き換えます。
- #{} を使用すると、SQL インジェクションを効果的に防止し、システム セキュリティを向上させることができます。
XMLマッピングファイルとMapperインターフェースの動作原理は何ですか
インターフェイスの完全修飾名はマッピング ファイルの名前空間の値であり、インターフェイスのメソッド名はマッピング ファイルの Mapper ステートメントの ID であり、インターフェイス メソッド パラメータは sql に渡されるパラメータです。Mapper インターフェースには実装クラスがありません。インターフェース メソッドが呼び出されると、インターフェースの完全修飾クラス名 + メソッド名がキー値として文字列に連結され、MapperStatement を一意に特定できます。
Mybatis の各 ,,, ラベルは MapperStatement オブジェクトに解析されます。Mapper インターフェイスのメソッドはオーバーロードできません。これは、完全な名前 + メソッド名を使用して戦略を保存および検索するためです。Mapper インターフェイスの動作原理は JDK 動的プロキシです. Mybatis は JDK 動的プロキシを使用して、実行時に Mapper インターフェイスのプロキシ オブジェクト プロキシを生成します. プロキシ オブジェクトはインターフェイス メソッドをインターセプトし、代わりに MapperStatement によって表される sql を実行します、そして sql 実行結果を返します。
Mybatis の一次キャッシュと二次キャッシュ
MyBatis キャッシュ: SQL クエリまたは SQL 更新を実行した後、この SQL ステートメントは消えませんが、MyBatis によってキャッシュされます. 同じ SQL ステートメントが再度実行されると、SQL を再実行するのではなく、キャッシュから直接抽出されます. その中で、MyBatis は一次キャッシュと二次キャッシュに分かれており、一次キャッシュは sqlSession レベル、二次キャッシュはテーブルレベル (1 マッパーと 1 キャッシュ) です。
レベル 1 キャッシュ: PerpetualCache に基づく HashMap ローカル キャッシュ。そのストレージ スコープは sqlSession です。セッションがフラッシュまたはクローズされると、セッション内のすべてのキャッシュがクリアされ、レベル 1 キャッシュがデフォルトで有効になります。
- 同じ SqlSession 内で、Mybatis は実行されたメソッドとパラメーターのアルゴリズムを介してキャッシュのキー値を生成し、そのキー値と結果を Map に格納し、その後のキー値が同じ場合は直接データを取得します。地図から;
- 異なる SqlSession 間のキャッシュは互いに分離されています。
- SqlSession を使用すると、クエリを実行する前にキャッシュをクリアするように構成できます。
- UPDATE、INSERT、DELETE ステートメントはキャッシュをクリアします。
- 失敗した場合:
- sqlSession が異なります。SQL ステートメントが同じであっても、2 回実行されます。
- sqlSession は同じですが、クエリ条件が異なります。
- sqlSession は同じで、クエリ条件も同じですが、追加、削除、および変更操作 (キャッシュのクリア) は 2 つのクエリ間で実行されます。
- sqlSeesion オブジェクトは同じで、2 つのクエリ条件は同じで、途中で追加、削除、または変更はありませんが、clearCache() メソッドが呼び出されます。
- MyBatis は、2 つのクエリについて、次の条件がまったく同じであれば、それらはまったく同じ 2 つのクエリであると見なされると考えています。
- 受信ステートメント ID。
- クエリで必要な結果セット内の結果の範囲。
- このクエリによって生成され、PreparedStatement に渡される最も重要な SQL ステートメント文字列と、設定されるパラメーター値。
Second-level cache: 複数の sqlSessions がキャッシュを共有する必要があるため、2 次キャッシュを有効にする必要があります.2 次キャッシュが有効になった後、Executor は CachingExecutor で装飾されます.最初のクエリプロセスに入る前に-レベル キャッシュの場合、第 2 レベルのキャッシュ クエリは CachingExecutor で実行されます。
-
The second-level cache is not enabled by default and needs to be enabled by manual. To implement the second-level cache MyBatis requires that the POJO returned must be serializable. セカンド レベル キャッシュを有効にするには、MyBatis で設定する必要があります。構成ファイル:
<settings> <setting name = "cacheEnabled" value = "true" /> </settings>
2 次キャッシュを有効にするには、Mapper の XML 構成ファイルにタグを追加する必要もあります。
-
失敗条件:
- 最初の SqlSession が送信されておらず、SQL ステートメントによって生成されたクエリ結果が二次キャッシュに配置されていないため、この時点で、2 番目の SqlSession はクエリ時に二次キャッシュの存在を感じることができません。
- UPDATE、INSERT、DELETE 操作がある場合、キャッシュはクリアされます
キャッシュの使用には注意してください: 複数テーブルの操作で、あるテーブルのキャッシュを更新すると、別のテーブルのキャッシュは引き続き有効であるため、クエリの結果が正しくなくなります。
MyBatis実行の流れ
- Mybatis 構成ファイルを読む: mybatis-config.xml は、Mybatis のグローバル構成ファイルであり、MyBatis の動作環境と、データベース接続情報などのその他の情報を構成します。
- ロード マッピング ファイル: データベースを操作するための SQL ステートメントを構成する SQL マッピング ファイルであり、MyBatis 構成ファイルにロードする必要があります。
- セッション ファクトリ SqlSessionFactory を構築します: MyBatis 環境およびその他の構成情報を介して構築します。
- セッション オブジェクトの作成: SqlSession オブジェクトは、SQL を実行するためのすべてのメソッドを含む SqlSessionFactory によって作成されます。
- Executor : Mybatis の最下層は、データベースを操作するための Executor インターフェイスを定義します.これは、SqlSession によって渡されるパラメーターに従って、実行する SQL ステートメントを動的に生成し、クエリキャッシュのメンテナンスを担当します.
- MappedStatement オブジェクト: Executor インターフェイスの実行メソッドには、マッピング情報をカプセル化し、マッピングする SQL ステートメントの ID、パラメーター、およびその他の情報を格納するために使用される MappedStatement 型のパラメーターがあります。
- 入力パラメーターのマッピング: 入力パラメーターの型は、Map や List などのコレクション型にすることも、基本データ型と POJO 型にすることもできます。このプロセスは、JDBC が PreparedStatement オブジェクトのパラメーターを設定するプロセスに似ています。
- 出力マップ
マッパーで複数のパラメーターを渡す方法
-
パラメータを順番に渡します。つまり #{0} #{1}
-
@Param アノテーションのパラメータの受け渡し方法
-
マップパラメータの受け渡し方法
-
Java Bean パラメータの受け渡し方法:
<select id="selectUser" parameterType="com.hty.pojo.User" resultMap="UserResultMap">
RESTful
HTTP をベースにした Web アプリケーションの設計スタイルと開発方法は、XML または JSON 形式で定義できます。
- 各 URI はリソースを表します
- クライアントは、GET、POST、PUT、および DELETE の 4 つの操作モードを使用して、サーバーのリソースを操作します。GET は取得に使用され、POST は作成または更新に使用され、PUT は更新に使用され、DELETE はリソースの削除に使用されます。