SpringAOPとAspectJの比較

1.はじめに

現在、利用可能なAOPライブラリは複数あり、これらはいくつかの質問に答えられる必要があります。

  • 既存または新規のアプリケーションと互換性がありますか?
  • AOPはどこに実装できますか?
  • どのくらい早く私のアプリケーションと統合されますか?
  • パフォーマンスのオーバーヘッドはどれくらいですか?

この記事では、これらの質問への回答を見て、Javaで最も人気のある2つのAOPフレームワークであるSpringAOPとAspectJを紹介します。

2.AOPの概念

始める前に、用語とコアコンセプトの簡単で高レベルのレビューを行いましょう。

  • アスペクト–アプリケーションの複数の場所に散在し、通常は実際のビジネスロジック(トランザクション管理など)とは異なる標準のコード/機能。各側面は、特定の分野横断的な機能に焦点を当てています
  • ジョインポイント–メソッドの実行、コンストラクターの呼び出し、フィールドの割り当てなどのプログラムの実行中の特定のポイントです。
  • アドバイス–特定のジョインポイントのアスペクトによって実行されるアクション
  • ポイントカット–ジョインポイントに一致する正規表現。参加ポイントがポイントカットに一致するたびに、そのポイントカットに関連付けられた指定されたアドバイスが実行されます
  • ウィービング–アスペクトをターゲットオブジェクトにリンクして、アドバイスされたオブジェクトを作成するプロセス

3. SpringAOPとAspectJ

それでは、機能、目標、織り方、内部構造、結合点、単純さなど、さまざまな軸にわたってSpringAOPとAspectJについて説明しましょう。

3.1。機能と目標

簡単に言えば、SpringAOPとAspectJには異なる目標があります。

Spring AOPは、プログラマーが直面する最も一般的な問題を解決するために、SpringIoC全体に単純なAOP実装を提供することを目的としています。これは完全なAOPソリューションとして意図されたものではありません。Springコンテナーによって管理されるBeanにのみ適用できます。

一方、AspectJは、完全なAOPソリューションを提供することを目的とした独自のAOPテクノロジーです。Spring AOPよりも堅牢ですが、かなり複雑です。AspectJはすべてのドメインオブジェクトに適用できることにも注意してください。

3.2。織り

AspectJとSpringAOPはどちらも、パフォーマンスと使いやすさに関する動作に影響を与える異なるタイプの織りを使用しています。

AspectJは、次の3種類の織りを利用しています。

  1. コンパイル時のウィービング:AspectJコンパイラーは、アスペクトのソースコードとアプリケーションの両方を入力として受け取り、ウィービングされたクラスファイルを出力として生成します。
  2. コンパイル後のウィービング:これは、バイナリウィービングとも呼ばれます。これは、既存のクラスファイルとJARファイルを私たちの側面で織り上げるために使用されます
  3. ロード時のウィービング:これは以前のバイナリウィービングとまったく同じですが、クラスローダーがクラスファイルをJVMにロードするまでウィービングが延期される点が異なります。

AspectJ自体の詳細については、この記事に進んでください。

AspectJはコンパイル時とクラスロード時のウィービングを使用するため、SpringAOPはランタイムウィービングを利用します

ランタイムウィービングでは、ターゲットオブジェクトのプロキシを使用してアプリケーションの実行中にアスペクトがウィービングされます– JDK動的プロキシまたはCGLIBプロキシ(次のポイントで説明)のいずれかを使用します。

3.3。内部構造とアプリケーション

Spring AOPは、プロキシベースのAOPフレームワークです。これは、ターゲットオブジェクトにアスペクトを実装するために、そのオブジェクトのプロキシを作成することを意味します。これは、次の2つの方法のいずれかを使用して実現されます。

  1. JDK動的プロキシ– SpringAOPに推奨される方法。ターゲットオブジェクトが1つのインターフェイスを実装する場合は常に、JDK動的プロキシが使用されます
  2. CGLIBプロキシ–ターゲットオブジェクトがインターフェイスを実装していない場合は、CGLIBプロキシを使用できます

Spring AOPプロキシメカニズムの詳細については、公式ドキュメントをご覧ください。

一方、AspectJは、クラスがアスペクトを使用して直接コンパイルされるため、実行時に何も実行しません。

そのため、Spring AOPとは異なり、デザインパターンは必要ありません。コードにアスペクトを織り込むために、AspectJコンパイラ(ajc)と呼ばれるコンパイラを導入します。これにより、プログラムをコンパイルし、小さな(<100K)ランタイムライブラリを提供して実行します。

3.4。参加ポイント

セクション3.3では、SpringAOPがプロキシパターンに基づいていることを示しました。このため、対象のJavaクラスをサブクラス化し、それに応じて横断的関心事を適用する必要があります。

ただし、制限があります。「最終」であるクラスに横断的関心事(またはアスペクト)を適用することはできません。これは、クラスをオーバーライドできないため、実行時例外が発生するためです。

同じことが静的メソッドとfinalメソッドにも当てはまります。スプリングアスペクトはオーバーライドできないため、適用できません。したがって、Spring AOPはこれらの制限があるため、メソッド実行のジョインポイントのみをサポートします。

ただし、AspectJは、実行前に横断的関心事を実際のコードに直接織り込みます。Spring AOPとは異なり、ターゲットオブジェクトをサブクラス化する必要がないため、他の多くの結合点もサポートします。サポートされている参加ポイントの概要は次のとおりです。

ジョインポイント SpringAOPをサポート AspectJがサポートされています
メソッド呼び出し 番号 はい
メソッドの実行 はい はい
コンストラクター呼び出し 番号 はい
コンストラクターの実行 番号 はい
静的初期化子の実行 番号 はい
オブジェクトの初期化 番号 はい
フィールドリファレンス 番号 はい
フィールド割り当て 番号 はい
ハンドラーの実行 番号 はい
アドバイスの実行 番号 はい

Spring AOPでは、同じクラス内で呼び出されるメソッドにアスペクトが適用されないことにも注意してください。

これは明らかに、同じクラス内のメソッドを呼び出すときに、SpringAOPが提供するプロキシのメソッドを呼び出さないためです。この機能が必要な場合は、異なるBeanで個別のメソッドを定義するか、AspectJを使用する必要があります。

3.5。シンプルさ

Spring AOPは、ビルドプロセスの間に追加のコンパイラーやウィーバーを導入しないため、明らかに単純です。ランタイムウィービングを使用するため、通常のビルドプロセスとシームレスに統合されます。シンプルに見えますが、Springによって管理されているBeanでのみ機能します。

ただし、AspectJを使用するには、AspectJコンパイラ(ajc)を導入し、すべてのライブラリを再パッケージ化する必要があります(コンパイル後またはロード時のウィービングに切り替えない限り)。

もちろん、これは前者よりも複雑です。これは、AspectJ Javaツール(コンパイラー(ajc)、デバッガー(ajdb)、ドキュメントジェネレーター(ajdoc)、プログラム構造ブラウザー(ajbrowser)を含む)を導入しているためです。 IDEまたはビルドツールのいずれかと統合する必要があります。

3.6。パフォーマンス

パフォーマンスに関する限り、コンパイル時のウィービングはランタイムのウィービングよりもはるかに高速です。Spring AOPはプロキシベースのフレームワークであるため、アプリケーションの起動時にプロキシが作成されます。また、アスペクトごとにさらにいくつかのメソッド呼び出しがあり、パフォーマンスに悪影響を及ぼします。

一方、AspectJは、アプリケーションが実行される前にアスペクトをメインコードに織り込むため、Spring AOPとは異なり、追加のランタイムオーバーヘッドはありません。

これらの理由から、ベンチマークは、AspectJがSpring AOPよりも約8〜35倍高速であることを示唆しています。

4.まとめ

このクイックテーブルは、SpringAOPとAspectJの主な違いをまとめたものです。

春のAOP AspectJ
純粋なJavaで実装 Javaプログラミング言語の拡張機能を使用して実装
個別のコンパイルプロセスは必要ありません LTWが設定されていない限り、AspectJコンパイラ(ajc)が必要です
ランタイムウィービングのみが利用可能です ランタイムウィービングは利用できません。コンパイル時、ポストコンパイル、およびロード時のウィービングをサポートします
あまり強力ではない–メソッドレベルのウィービングのみをサポート より強力–フィールド、メソッド、コンストラクター、静的初期化子、最終クラス/メソッドなどを織り込むことができます…
Springコンテナで管理されているBeanにのみ実装できます すべてのドメインオブジェクトに実装できます
メソッド実行ポイントカットのみをサポート すべてのポイントカットをサポートする
プロキシはターゲットオブジェクトで作成され、アスペクトはこれらのプロキシに適用されます アプリケーションが実行される前(実行前)に、アスペクトがコードに直接織り込まれます
AspectJよりもはるかに遅い よりよい性能
習得と適用が簡単 SpringAOPよりも比較的複雑

5.適切なフレームワークの選択

このセクションで行われたすべての議論を分析すると、あるフレームワークが別のフレームワークよりも優れているとは限らないことが理解され始めます。

簡単に言えば、選択は私たちの要件に大きく依存します:

  • フレームワーク:アプリケーションがSpringフレームワークを使用していない場合、Springコンテナの範囲外のものを管理できないため、SpringAOPを使用するという考えを捨てるしかありません。ただし、アプリケーションが完全にSpringフレームワークを使用して作成されている場合は、習得と適用が簡単であるため、SpringAOPを使用できます。
  • 柔軟性:ジョインポイントのサポートが限られているため、Spring AOPは完全なAOPソリューションではありませんが、プログラマーが直面する最も一般的な問題を解決します。AOPをさらに深く掘り下げて最大限に活用し、利用可能なさまざまな参加ポイントからのサポートが必要な場合は、AspectJが選択されます。
  • パフォーマンス:限られた側面を使用している場合、パフォーマンスにはわずかな違いがあります。ただし、アプリケーションに数万を超える側面がある場合があります。このような場合はランタイムウィービングを使用したくないので、AspectJを選択することをお勧めします。AspectJはSpringAOPより8〜35倍高速であることが知られています
  • 両方の長所:これらのフレームワークは両方とも完全に互換性があります。可能な場合はいつでもSpringAOPを利用できますが、AspectJを使用して、前者ではサポートされていない参加ポイントのサポートを取得できます。

6.結論

この記事では、SpringAOPとAspectJの両方をいくつかの重要な領域で分析しました。

AOPへの2つのアプローチを、柔軟性と、アプリケーションにどれだけ簡単に適合するかについて比較しました。