私はアスペクト指向プログラミングの概念とSpring AOPを学んでいます。ポイントカットとジョインポイントの違いを理解できていません。どちらも同じように見えます。ポイントカットはアドバイスを適用する場所であり、ジョインポイントはアドバイスを適用できる場所でもあります。次に、違いは何ですか?
ポイントカットの例は次のとおりです。
@Pointcut("execution(* * getName()")
ジョインポイントの例は何ですか?
回答:
ジョインポイント:ジョインポイントは、アスペクトをプラグインできるアプリケーションのプログラム実行の候補ポイントです。このポイントは、メソッドの呼び出し、例外のスロー、またはフィールドの変更である可能性があります。これらは、アスペクトのコードをアプリケーションの通常のフローに挿入して、新しい動作を追加できるポイントです。
アドバイス:これは、ポイントで指定されたジョインポイントで実行するアクションを表す、システム全体の懸念に対するAPI呼び出しを含むオブジェクトです。
ポイントカット:ポイントカットは、どのジョインポイントに関連するアドバイスを適用するかを定義します。アドバイスは、AOPフレームワークでサポートされている任意の結合点に適用できます。もちろん、考えられるすべてのジョインポイントにすべての側面を適用する必要はありません。ポイントカットを使用すると、アドバイスを適用する場所を指定できます。多くの場合、これらのポイントカットは、明示的なクラス名とメソッド名を使用するか、一致するクラス名とメソッド名のパターンを定義する正規表現を使用して指定します。一部のAOPフレームワークでは、メソッドパラメーターの値などの実行時の決定に基づいてアドバイスを適用するかどうかを決定する動的ポイントカットを作成できます。
次の画像は、アドバイス、ポイントカット、ジョインポイントを理解するのに役立ちます。
Restaurant Analogyを使用した説明: @Victorによるソース
レストランに出かけるときは、メニューを見て、いくつかのオプションから選択します。メニューのアイテムを1つ以上注文できます。しかし、実際に注文するまでは、「食事する機会」に過ぎません。注文すると、ウェイターがそれをあなたのテーブルに持ってきたら、それは食事です。
ジョインポイントはメニューのオプションであり、ポイントカットはユーザーが選択するアイテムです。
ジョインポイントは、アスペクトを適用するためのコード内の機会です...単なる機会です。その機会を利用して1つ以上のジョインポイントを選択し、それらにアスペクトを適用すると、ポイントカットが得られます。
ソースWiki:
参加点は、制御フローを介して到着することができ、プログラムの制御フロー内の点である2つの異なるパス(なぜコールジョイントのIMO)。
アドバイスは、他の関数を変更する関数のクラスを記述します
ポイントカットは、参加点の集合です。
more Joinpoints and apply an aspect to them, you've got a Pointcut.
彼らへの側面や彼らへのアドバイス?
ジョインポイントとポイントカットの違いを理解するには、ポイントカットをウィービングルールを指定し、ジョインポイントをそれらのルールを満たす状況として指定することを考えてください。
以下の例では、
@Pointcut("execution(* * getName()")
ポイントカットはルールを定義しており、アドバイスはパッケージ内のクラスに存在するgetName()メソッドに適用する必要があり、ジョインポイントはクラスに存在するすべてのgetName()メソッドのリストになるため、これらのメソッドにアドバイスを適用できます。
(Springの場合、ルールはマネージドBeanにのみ適用され、アドバイスはパブリックメソッドにのみ適用できます)。
JoinPoints:これらは基本的に、実際のビジネスロジックの一部であり、必要ではないが実際のビジネスロジックの一部ではないその他の機能を挿入する場所です。JoinPintsの例としては、メソッドの呼び出し、正常に戻るメソッド、例外のスロー、オブジェクトのインスタンス化、オブジェクトの参照などがあります。
ポイントカット:ポイントカットは、ジョインポイントを識別するために使用されている正規表現のようなものです。ポンカットは「ポイントカット表現言語」で表現されています。ポイントカットは、横断的関心事を適用する必要がある実行フローのポイントです。ジョインポイントとポイントカットには違いがあります。ジョインポイントはより一般的であり、横断的関心事を「選択」する可能性のある制御フローを表しますが、ポイントカットは、横断的関心事を導入したい結合ポイントを識別します。
AOPの概念に不慣れな人のためのレイマンの説明。これは完全なものではありませんが、概念を理解するのに役立ちます。基本的な専門用語に既に慣れている場合は、今すぐ読み進めるのをやめることができます。
通常のクラスEmployeeがあり、これらのメソッドが呼び出されるたびに何かを実行したいとします。
class Employee{
public String getName(int id){....}
private int getID(String name){...}
}
これらのメソッドはJoinPointsと呼ばれます。フレームワークがロードしたすべてのclasses.methodsからメソッドを見つけることができるように、これらのメソッドを識別する方法が必要です。したがって、これらのメソッドのシグネチャに一致する正規表現を記述します。以下に示すように、他にもありますが、大まかに言えば、この正規表現がPointcutを定義しています。例えば
* * mypackage.Employee.get*(*)
最初の*は、修飾子public / private / protected / defaultを表します。2番目の*はメソッドの戻り値の型です。
ただし、さらに2つのことを伝える必要があります。
これら2つの組み合わせをアドバイスと呼びます。
ご想像のとおり、#2を実行できるようにするには、関数を作成する必要があります。したがって、これは基本的には次のようになります。
注:明確にするために、の代わりにREGEXという単語を使用し* * mypackage.Employee.get*(*)
ます。実際には、完全な表現が定義に入ります。
@Before("execution(REGEX)")
public void doBeforeLogging() {....} <-- executed before the matching-method is called
@After("execution(REGEX)")
public void doAfterLogging() {....} <-- executed after the matching-method is called
これらをかなり使い始めると、多くの@ After / @ Before / @ Aroundアドバイスを指定することになります。繰り返し正規表現は最終的に物事が混乱し、維持するために困難になってしまいます。したがって、実行することは、式に名前を付けて、Aspectクラスの他のすべての場所で使用することです。
@Pointcut("execution(REGEX)") <-- Note the introduction of Pointcut keyword
public void allGetterLogging(){} <-- This is usually empty
@Before("allGetterLogging")
public void doBeforeLogging() {....}
@After("allGetterLogging")
public void doAfterLogging() {....}
ところで、このロジック全体をAspectと呼ばれるクラスにラップし、クラスを作成することもできます。
@Aspect
public class MyAwesomeAspect{....}
これらすべてを機能させるには、クラスを解析して@ AOPキーワードを読み取り、理解し、アクションを実行するようにSpringに指示する必要があります。これを行う1つの方法は、Spring構成xmlファイルで以下を指定することです。
<aop:aspectj-autoproxy>
ドキュメントに従って:
結合ポイント:メソッドの実行や例外の処理など、プログラムの実行中のポイント。
ジョイントポイントは、プログラムの実行中のイベントと見なすことができます。Spring AOPを使用している場合、これはメソッドの呼び出しに限定されます。AspectJはより高い柔軟性を提供します。
しかし、レストランに行くとき、メニューのすべての食べ物を食べないので、すべてのイベントを処理することはありません(私はあなたを知らないので、あなたはそうかもしれません!したがって、処理するイベントとそれらをどうするかを選択します。ここにポイントカットがあります。ドキュメントに従って、
ポイントカット:結合ポイントに一致する述語。
そして、あなたは何を行うに関連付けるポイントカット、そこに行くのアドバイスを。ドキュメントに従って、
アドバイスはポイントカット式に関連付けられており、ポイントカットに一致する任意の結合ポイントで実行されます。
package com.amanu.example;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* @author Amanuel Nega on 10/25/16.
*/
class ExampleBussinessClass {
public Object doYourBusiness() {
return new Object();
}
}
@Aspect
class SomeAspect {
@Pointcut("execution(* com.amanu.example.ExampleBussinessClass.doYourBusiness())")
public void somePointCut() {
}//Empty body suffices
@After("somePointCut()")
public void afterSomePointCut() {
//Do what you want to do after the joint point is executed
}
@Before("execution(* *(*))")
public void beforeSomePointCut() {
//Do what you want to do before the joint point is executed
}
}
ExampleBusinessClass
プロキシされたとき、それが私たちの目標です!doYourBusiness()
可能なジョイントポイントですSomeAspect
お尻のような複数の懸念に交差する私たちの側面です ExampleBusinessClass
somePointCut()
ジョイントポイントに一致するポイントカットの定義ですafterSomePointCut()
あるアドバイス私たちの後に実行されるsomePointCut
ポイントカットと一致するdoYourBusiness()
接続点は、beforeSomePointCut()
また、すべてのメソッド実行に一致するアドバイスですpublic
。とは異なりafterSomePointCut
、これはインラインポイントカット宣言を使用します。信じられない場合は、ドキュメントをご覧ください。これが役に立てば幸い
どちらもアスペクト指向プログラミングの「どこ」に関係しています。
参加ポイントは、AOPでコードを実行できる個別の場所です。たとえば、「メソッドが例外をスローしたとき」などです。
ポイントカットは、結合ポイントのコレクションです。たとえば、「クラスFooのメソッドが例外をスローしたとき」などです。
春のAOPには{アドバイザー、アドバイス、ポイントカット、ジョインポイント}があります。
ご存知のように、aopの主な目的は、横断的な関心ロジック(アスペクト)をアプリケーションコードから分離することです。これをSpringで実装するには、次のように使用します(アドバイス/アドバイザー)。
「すべてのメソッドは挿入で始まる」のように、このアドバイスを適用したい場所をフィルタリングするためにポイントカットが使用されるため、他のメソッドは除外されます。そのため、ポイントカットインターフェイス{ClassFilter and MethodMatcher}にあります。
したがって、Adviceは横断的なロジックの実装であり、AdvisorはアドバイスとPointCutです。アドバイスのみを使用する場合、SpringはそれをAdvisorにマップし、ポイントカットをTRUEにして、何もブロックしないようにします。そのため、アドバイスのみを使用すると、フィルター処理を行わなかったため、ターゲットクラスのすべてのメソッドに適用されます。
しかし、Joinpointはプログラム内の場所です。Classオブジェクトにアクセスすると、リフレクションのように考えることができ、次にMethodオブジェクトを取得して、このクラスの任意のメソッドを呼び出すことができます。コンパイラが機能する方法は、次のとおりです。これはジョインポイントを想像できます。
ジョインポイントはフィールド、コンストラクター、またはメソッドで使用できますが、Springではメソッドのみのジョインポイントがあるため、Springでは(Before、After、Throws、Around)タイプのジョインポイントがあり、それらはすべてクラス内の場所を参照します。
ポイントカットなし(フィルターなし)のアドバイスがある場合は、前述のように、すべてのメソッドに適用されます。特定のメソッドに適用される[アドバイス+ポイントカット]のアドバイザーを持つことはできますが、アドバイスなしにはアドバイスできません。 pointcutのようなjoinpointは指定する必要があります。そのため、Springのアドバイスタイプはjoinpointとまったく同じタイプなので、アドバイスを選択すると、暗黙的にどのジョインポイントを選択するかが決まります。
まとめると、アドバイスは、ターゲットクラスに対するアスペクトの実装ロジックです。このアドバイスには、呼び出し前、呼び出し後、スロー後、または呼び出し前後のような結合点が必要です。pointcutを使用して適用する場所を正確にフィルタリングできます。メソッドをフィルタリングするか、ポイントカットなし(フィルターなし)にすることで、クラスのすべてのメソッドに適用されます。
ポイントカットは、アスペクト-クラス実装で定義されます。ポイントカットは、基本的にアドバイス内のポイントカット表現を指します。
たとえば、
@Before("execution(* app.purchase2.service.impl.*(..))")
public void includeAddOns(RolesAllowed roles) {
..
}
上記は、(@ Beforeのアドバイスにより)呼び出し前に「includeAddOns」メソッドが呼び出されることを意味します(パッケージ「app.purchase2.service.impl」内のクラス内)
注釈全体はポイントカットと呼ばれます
@Before("execution(* app.purchase2.service.impl.*(..))")
ジョイントポイントは、パッケージ「app.purchase2.service.impl」のメソッドをアスペクトクラス「includeAddOns()」のメソッドに結合した実際のメソッド呼び出しです。
org.aspectj.lang.JoinPoint
クラスを使用して、結合ポイントのプロパティにアクセスできます。
参加ポイントは、実際にアドバイスを配置する場所です
ただし、ポイントカットは結合ポイントのコレクションです。つまり、クロスカットロジックを配置する方法をポイントカットと呼びます。