Spring AOPとAspectJの比較
1. 前書き
現在、複数の利用可能なAOPライブラリがあり、これらはいくつかの質問に答えることができる必要があります。
-
既存または新規のアプリケーションと互換性がありますか?
-
AOPはどこで実装できますか?
-
アプリケーションとどのくらい早く統合されますか?
-
パフォーマンスのオーバーヘッドは?
この記事では、これらの質問への回答を見て、Javaで最も人気のある2つのAOPフレームワークであるSpringAOPとAspectJを紹介します。
2. AOPの概念
始める前に、用語とコアコンセプトの簡単で高レベルのレビューを行いましょう。
-
アスペクト-**アプリケーション内の複数の場所に散在し、通常は実際のビジネスロジック(トランザクション管理など)とは異なる標準コード/機能。 各側面は、特定の横断的な機能に焦点を当てています
-
ジョインポイント– **メソッドの実行、コンストラクターの呼び出し、フィールドの割り当てなどのプログラムの実行中の特定のポイントです
-
アドバイス–特定のジョインポイントでアスペクトがとるアクション
-
ポイントカット–ジョインポイントに一致する正規表現。 結合ポイントがポイントカットに一致するたびに、そのポイントカットに関連付けられた指定のアドバイスが実行されます
-
ウィービング-アスペクトをターゲットオブジェクトにリンクして、推奨オブジェクトを作成するプロセス
3. SpringAOPとAspectJ
それでは、機能、目標、織り方、内部構造、結合点、単純さなど、さまざまな軸にわたってSpringAOPとAspectJについて説明しましょう。
3.1. 機能と目標
簡単に言えば、Spring AOPとAspectJには異なる目標があります。
Spring AOPは、プログラマーが直面する最も一般的な問題を解決するために、Spring IoC全体に単純なAOP実装を提供することを目指しています。 It is not intended as a complete AOP solution –Springコンテナによって管理されるBeanにのみ適用できます。
一方、AspectJ is the original AOP technology which aims to provide complete AOP solution.は、Spring AOPよりも堅牢ですが、かなり複雑です。 AspectJはすべてのドメインオブジェクトに適用できることにも注意してください。
3.2. 機織り
AspectJとSpring AOPは両方とも、パフォーマンスと使いやすさに関する動作に影響する異なる種類の織り方を使用します。
AspectJは、3種類の織り方を使用します。
-
Compile-time weaving:AspectJコンパイラーは、アスペクトのソースコードとアプリケーションの両方を入力として受け取り、出力として織り込まれたクラスファイルを生成します。
-
Post-compile weaving:これはバイナリウィービングとも呼ばれます。 これは、既存のクラスファイルとJARファイルをアスペクトで織り込むために使用されます
-
Load-time weaving:これは以前のバイナリウィービングとまったく同じですが、クラスローダーがクラスファイルをJVMにロードするまでウィービングが延期される点が異なります。
AspectJ自体の詳細については、head on over to this articleを参照してください。
AspectJはコンパイル時とクラスロード時のウィービングを使用するため、Spring AOP makes use of runtime weaving。
ランタイムウィービングでは、ターゲットオブジェクトのプロキシを使用してアプリケーションの実行中にアスペクトが織り込まれます。JDK動的プロキシまたはCGLIBプロキシ(次のポイントで説明します)を使用します。
3.3. 内部構造とアプリケーション
Spring AOPは、プロキシベースのAOPフレームワークです。 これは、ターゲットオブジェクトにアスペクトを実装するために、そのオブジェクトのプロキシを作成することを意味します。 これは、次の2つの方法のいずれかを使用して実現されます。
-
JDK動的プロキシ– Spring AOPの推奨方法。 ターゲットオブジェクトが1つのインターフェースさえ実装する場合は常に、JDK動的プロキシが使用されます
-
CGLIBプロキシ–ターゲットオブジェクトがインターフェイスを実装していない場合は、CGLIBプロキシを使用できます
Spring AOPプロキシメカニズムについては、the official docsから詳しく知ることができます。
一方、AspectJは、クラスがアスペクトを使用して直接コンパイルされるため、実行時に何も実行しません。
そのため、Spring AOPとは異なり、デザインパターンは必要ありません。 コードにアスペクトを織り込むために、AspectJコンパイラー(ajc)として知られるコンパイラーを導入します。これにより、プログラムをコンパイルし、小さな(100K未満の)ランタイムライブラリを提供して実行します。
3.4. 参加ポイント
セクション3.3では、Spring AOPがプロキシパターンに基づいていることを示しました。 このため、対象のJavaクラスをサブクラス化し、それに応じて横断的な関心事を適用する必要があります。
ただし、制限があります。 We cannot apply cross-cutting concerns (or aspects) across classes that are “final” because they cannot be overridden and thus it would result in a runtime exception.
同じことが静的メソッドと最終メソッドにも当てはまります。 それらはオーバーライドできないため、Springのアスペクトはそれらに適用できません。 したがって、Spring AOPはこれらの制限のため、メソッド実行の結合点のみをサポートします。
ただし、AspectJ weaves the cross-cutting concerns directly into the actual code before runtime. Spring AOPとは異なり、ターゲットオブジェクトをサブクラス化する必要がないため、他の多くの結合点もサポートします。 サポートされているジョインポイントの概要は次のとおりです。
ジョインポイント | SpringAOPをサポート | AspectJがサポートされています |
---|---|---|
メソッド呼び出し |
No |
Yes |
メソッドの実行 |
Yes |
Yes |
コンストラクター呼び出し |
No |
Yes |
コンストラクターの実行 |
No |
Yes |
静的初期化子の実行 |
No |
Yes |
オブジェクトの初期化 |
No |
Yes |
フィールドリファレンス |
No |
Yes |
フィールド割り当て |
No |
Yes |
ハンドラーの実行 |
No |
Yes |
アドバイスの実行 |
No |
Yes |
Spring AOPでは、同じクラス内で呼び出されるメソッドにアスペクトが適用されないことにも注意してください。
これは明らかに、同じクラス内のメソッドを呼び出すときに、SpringAOPが提供するプロキシのメソッドを呼び出さないためです。 この機能が必要な場合は、異なるBeanで個別のメソッドを定義するか、AspectJを使用する必要があります。
3.5. 単純さ
Spring AOPは、ビルドプロセスの間に追加のコンパイラやウィーバーを導入しないため、明らかに単純です。 ランタイムウィービングを使用するため、通常のビルドプロセスとシームレスに統合されます。 シンプルに見えますが、Springによって管理されるBeanでのみ機能します。
ただし、AspectJを使用するには、AspectJコンパイラ(ajc)を導入し、すべてのライブラリを再パッケージ化する必要があります(ポストコンパイルまたはロード時のウィービングに切り替えた場合を除く)。
もちろん、これは前者よりも複雑です。AspectJJava Tools(コンパイラ(ajc)、デバッガ(ajdb)、ドキュメントジェネレータ(ajdoc)、プログラム構造ブラウザ(ajbrowser)を含む)を導入しているためです。 IDEまたはビルドツールのいずれかと統合する必要があります。
3.6. パフォーマンス
パフォーマンスに関する限り、compile-time weaving is much faster than runtime weaving。 Spring AOPはプロキシベースのフレームワークであるため、アプリケーションの起動時にプロキシが作成されます。 また、アスペクトごとにメソッド呼び出しがさらにいくつかあり、パフォーマンスに悪影響を及ぼします。
一方、AspectJは、アプリケーションが実行される前にアスペクトをメインコードに織り込むため、Spring AOPとは異なり、追加のランタイムオーバーヘッドはありません。
これらの理由から、benchmarksは、AspectJがSpring AOPよりも約8〜35倍高速であることを示しています。
4. 概要
この簡単な表は、Spring AOPとAspectJの主な違いをまとめたものです。
春のAOP | アスペクトJ |
---|---|
純粋なJavaで実装 |
Javaプログラミング言語の拡張機能を使用して実装 |
個別のコンパイルプロセスは必要ありません |
LTWが設定されていない限り、AspectJコンパイラ(ajc)が必要です |
ランタイムウィービングのみが利用可能です |
ランタイムウィービングは利用できません。 コンパイル時、ポストコンパイル、およびロード時のウィービングをサポートします |
あまり強力ではない–メソッドレベルのウィービングのみをサポート |
より強力–フィールド、メソッド、コンストラクター、静的初期化子、最終クラス/メソッドなどを織り込むことができます… |
Springコンテナで管理されているBeanにのみ実装できます |
すべてのドメインオブジェクトに実装できます |
メソッド実行ポイントカットのみをサポート |
すべてのポイントカットをサポートする |
プロキシはターゲットオブジェクトで作成され、アスペクトはこれらのプロキシに適用されます |
アプリケーションが実行される前(実行前)に、アスペクトがコードに直接織り込まれます |
AspectJよりもはるかに遅い |
よりよい性能 |
習得と適用が簡単 |
SpringAOPよりも比較的複雑 |
5. 適切なフレームワークの選択
このセクションで行われたすべての議論を分析すると、あるフレームワークが別のフレームワークよりも優れているわけではないことが理解できるようになります。
簡単に言えば、選択は要件に大きく依存します。
-
フレームワーク:アプリケーションがSpringフレームワークを使用していない場合、Springコンテナの範囲外のものを管理できないため、SpringAOPを使用するという考えを捨てるしかありません。 ただし、アプリケーションが完全にSpringフレームワークを使用して作成されている場合は、学習と適用が簡単であるため、SpringAOPを使用できます。
-
柔軟性:ジョインポイントのサポートが限られているため、Spring AOPは完全なAOPソリューションではありませんが、プログラマが直面する最も一般的な問題を解決します。 さらに深く掘り下げてAOPを最大限に活用し、利用可能な幅広いジョインポイントからのサポートが必要な場合は、AspectJが最適です
-
パフォーマンス:限られた側面を使用している場合、パフォーマンスにはわずかな違いがあります。 しかし、アプリケーションに数万以上の側面がある場合があります。 このような場合はランタイムウィービングを使用したくないため、AspectJを選択する方が良いでしょう。 AspectJは、Spring AOPよりも8〜35倍高速であることが知られています。
-
両方の長所:これらのフレームワークは両方とも互いに完全に互換性があります。 可能な場合はいつでもSpringAOPを利用できますが、AspectJを使用して、前者ではサポートされていない参加ポイントのサポートを取得できます。
6. 結論
この記事では、Spring AOPとAspectJの両方をいくつかの重要な領域で分析しました。
AOPに対する2つのアプローチを、柔軟性とアプリケーションへの適合性の両方で比較しました。