SpringBoot AOP入門

春といえば、私たちはその中核機能の二つが、ここで、AOP(アスペクト指向)とIOC(制御の反転)にAOPの使用を統合する方法SpringBootを要約する物品であることを知っています。

まず、サンプルアプリケーションのシナリオ:ログをカットするために、すべてのWeb要求。

1、POM導入SpringBootのWebモジュールとAOPを使用して関連する依存関係:
================================== ============

<依存性> 
<のgroupId> org.springframework.boot </のgroupId>
<たartifactId>ばねブートスタータAOP </たartifactId>
<バージョン> 2.1.5.RELEASE </バージョン>
</依存>
<依存性>
<のgroupId > org.aspectj </のgroupId>
<たartifactId> aspectjrt </たartifactId>
<バージョン> 1.8.9 </バージョン>
</依存>
<依存性>
<のgroupId> org.aspectj </のgroupId>
<たartifactId> aspectjweaver </たartifactId >
<バージョン> 1.6.11 </バージョン>
</依存関係>
<依存>
<groupIdを> CGLIB </ groupIdを>
<たartifactId> CGLIB </たartifactId>
<バージョン> 2.1 </ version>の
</依存関係>
================================================== ==========


前記
CGLIBパッケージは動的プロキシ、ベースのプロキシに使用される;
aspectjrtのaspectjweaverとプログラミング支持部用のAspectJのパッケージに関連付けられている、
AspectJのパッケージは、ランタイムパッケージであるaspectjrt、
AspectJのパッケージの中に織り込まれaspectjweaver。

2、簡単な達成するための入口Web要求(渡された関数の実現名パラメータを、の「ハローXXX」を返します):


注:AOPの依存関係の導入の終了時に、一般的には、追加の設定は必要ありません。人々の使用済み春の注釈の設定がマスター・クラスを使用可能にするプログラムで@EnableAspectJAutoProxyを増やす必要があるかどうか聞いてきます、実際には必要ありません。

なぜならAOPのデフォルトの構成プロパティの後、spring.aop.autoプロパティは限りAOP依存性の導入など、デフォルトは@EnableAspectJAutoProxyが増加していることを意味し、デフォルトで有効になっています。

3、アスペクトクラスの定義、Webログスライス層を実装

、クラスのカテゴリに2つのステップをカットを入れて
①アスペクトクラスカテゴリに@Componentアノテーションを使用すると、容器IOCに追加された
アスペクトクラスのクラスを作る際に使用②@Aspect注釈

パッケージcom.example.aop。

輸入org.aspectj.lang.JoinPoint。
輸入org.aspectj.lang.annotation.AfterReturning。
輸入org.aspectj.lang.annotation.Aspect;
輸入org.aspectj.lang.annotation.Before;
輸入org.aspectj.lang.annotation.Pointcut;
輸入org.slf4j.Logger。
輸入org.slf4j.LoggerFactory;
輸入org.springframework.stereotype.Component。
輸入org.springframework.web.context.request.RequestContextHolder。
輸入org.springframework.web.context.request.ServletRequestAttributes。
インポートのjavax.servlet.http.HttpServletRequest;
輸入java.util.Arrays。

/ **
* 2018年9月5日にLMBによって作成されました。
* /
@Aspect
@Component
パブリッククラスWebLogAcpect {

プライベートロガーロガー= LoggerFactory.getLogger(WebLogAcpect.class)。

/ **
*すべての関数のエントリポイントで定義されたエントリポイントはcom.example.aop
* /
@Pointcut( "実行(公共com.example.aop .. * *。*(..))")
公共無効ウェブログ(){}

/ **
*事前通知:通知は、接続点の前に実行される
* @paramジョインポイント
*のThrowable @throws
* /
@Before(「ウェブログ()」)
公共ボイドdoBefore(ジョインポイントジョインポイント)がThrowableをスロー{
//要求を受信し、記録要求されたコンテンツの
ServletRequestAttributesは)(=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes属性、
HttpServletRequestのattributes.getRequest要求=();

//下さい请求内容记录
logger.info( "URL:"。+ request.getRequestURL()のtoString());
logger.info( "HTTP_METHOD:" + request.getMethod());
logger.info( "IP:" + request.getRemoteAddr());
logger.info( "CLASS_METHOD:"。 ""。+ joinPoint.getSignature()getDeclaringTypeName()+ + joinPoint.getSignature()のgetName());
logger.info( "ARGS:" + Arrays.toString(joinPoint.getArgs()));
}

@AfterReturning( "RET"を返す=、ポイントカットは= "ブログは、()")
公共ボイドdoAfterReturning(オブジェクトRET)Throwableをスロー{
//終了処理要求を、コンテンツ返す
;(+ RET "応答")logger.infoを
}
}

上記リクエスト記録によって返されたオブジェクトを@AfterReturning com.example.aop入力パケット、事前通知@Beforeによって達成エントリポイントで実行されたすべての機能のための出発点によって定義@Pointcutアスペクトクラス。

 

第二に、AOPのサポート気づく
1、事前通知@Beforeを:アドバイスが実行されるように、それは例外をスローしない限り、ポイントに参加する前に、それ以外の通知は、接続点の前に実行の流れを止めることはできません。

/ **
*事前通知方法の前に呼び出されるコールする
* @paramジョインポイント/ nullに
* /
@Before(値= POINT_CUT)
ジョインポイントジョインポイント)前ます。public void {
logger.info( "事前通知");
//取得しますターゲットメソッドのパラメータ情報
オブジェクト[] joinPoint.getArgs OBJ =();
// AOPプロキシクラス情報
joinPoint.getThis();
//プロキシ対象物
joinPoint.getTarget();
最も//署名付き通知
署名= joinPoint.getSignatureシグネチャ();
//メソッドである薬剤
logger.infoは(+ signature.getName()「の方法である薬剤」);
//プロキシクラスAOPの名前
logger.info(「AOP剤クラス名「+ signature.getDeclaringTypeName());
// AOPプロキシクラスのカテゴリ(クラス)情報
signature.getDeclaringType();
//取得RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes()。
//从获取RequestAttributes中获取のHttpServletRequest的信息
のHttpServletRequest要求=(HttpServletRequestの)requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST)。
//如果要获取セッション信息的话、可以这样写:
// HttpSessionのセッション=(HttpSessionの)requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION)。
//获取请求参数
列挙<string>に列挙= request.getParameterNames()。
地図<文字列、文字列>なparameterMap = Maps.newHashMap();
一方、(enumeration.hasMoreElements()){
Stringパラメータ= enumeration.nextElement()。
parameterMap.put(パラメータ、request.getParameter(パラメータ))。
}
JSON.toJSONString STR =文字列(なparameterMap);
IF(obj.length> 0){
logger.info( "パラメータ情報要求である:" + STR);
}
}

アドバイス@Around約5:メソッド呼び出しとして通知の接続点を囲む、などが挙げられます。これは、アドバイスの中で最も強力なものです。アドバイスの周りメソッド呼び出しの前と後のカスタム動作を実行することができ、それが接続ポイントを続行するか、直接バック独自の戻り値または例外の実行を投げるかどうかを選択します。

最も強力で最も厄介なアドバイスの周りには、この方法を実行するために、この方法によりプロキシ経由のセクションに渡される具体的な方法、選択可能なカットかどうかを囲まれており、この方法は、複数回行います。アドバイスの周りにターゲットオーディエンスを管理するためのオブジェクトのプロキシProceedingJoinPointタイプを使用するので、この通知の最初のパラメータはProceedingJoinPointタイプでなければなりません。()通知のメソッドProceedingJoinPoint進行本体を呼び出すメソッドのバックグラウンドの接続点が実行させます。進行()メソッドは、メソッドが実行されたときに[]配列の値が基準として使用されているオブジェクトを渡しと呼ばれてもよいです。

/ **
*アドバイス周り:
*アドバイスを中心に非常に強力で、終了の戻り値を交換する必要があるかどうか、実行メソッドのパラメータを交換する必要があるかどうか、実行対象の方法、かどうかを判断することができます。
*サラウンド最初のパラメータはorg.aspectj.lang.ProceedingJoinPointタイプが通知されなければならない
* /
@Around(値= POINT_CUT)
パブリックオブジェクトdoAroundAdvice(ProceedingJoinPoint ProceedingJoinPoint){
+ proceedingJoinPoint:logger.info( "ターゲット通知メソッド名を囲みました"。 getSignature()のgetName());.
試み{
オブジェクトOBJ = proceedingJoinPoint.proceed();
OBJを返す;
}キャッチ(ThrowableをThrowableの){
Throwable.printStackTrace();
}
戻りNULL;
}

。6、時には我々は時間区間を定義します、セクションでは、それを得るために、対象物の切断パラメータを作成する方法、ターゲットオブジェクトにパラメータを使用する必要がありますか?argsが結合するために使用することができます。あなたは場所の名前を入力すると、オブジェクトの循環が渡されるときにするときのパラメータ値、パラメータ名を使用して引数式で使用する必要があります。

@Before( "実行(* findById *(..))&&" + "引数(ID、..)")
公共ボイドtwiceAsOld1(ロングID){
System.err.println( "切面执行了前.... ID ==」+ ID);

}

注:任意の通知方法は、第1パラメータタイプorg.aspectj.lang.JoinPoint(通知は、ジョインポイントのサブクラスである第1のパラメータ型ProceedingJoinPoint、周囲に定義される必要がある)として定義することができます。ジョインポイントインターフェイス例えばgetArgsとして有用な方法、(の数を提供する)(メソッドの引数を返す)、getThis()(プロキシを返す)でgetTarget()(戻りターゲット)、getSignature()(復帰方法は、情報を通知されます)そして、のtoString()(有用な情報方法が通知されているプリントアウト)。

第三に、ポイントカット表現
定義されたエントリポイント時に署名の名前と任意のパラメータ、ならびに実行などのエントリポイントの式を、含める必要性(パブリック* com.example.aop ...(.. ))

ポイントカット表現形式:実行([可視]リターンタイプ[宣言された型]メソッド名(パラメータ)[例外])
[]オプションで、さらにワイルドカードの使用をサポート:
1)* :すべての文字に一致
2)..:通常、複数のパケットを一致させるため、複数のパラメータ
3)+:クラスを表し、そのサブクラスは
、||、&&:4)演算子は!

実施例で使用されるキーワード表現をポイントカット:
1)実行:マッチングサブ式。
// com.cjm.modelマッチングパケットとそのサブパッケージのすべてのクラスのすべてのメソッド、戻り値の型、いずれかの、いずれかの方法でパラメータ
@Pointcut(「実行(* com.cjm.model ... (..))」)
公共ボイド前(){}

2)内:Javaクラスまたはパッケージマッチング接続点。
Personクラスマッチング//全ての方法
@Pointcut(「WITHIN(com.cjm.model.Person)」)
前公共ボイド){}
//すべての方法は、一致するパケットとすべてのクラスのサブパケットをcom.cjm
@Pointcut( "WITHIN(com.cjm .. *)")
パブリックボイド(){}前

3)これは:通知方法基準に着信プロキシオブジェクトの。
( "前()&&この(プロキシ)")@Before
公共ボイドbeforeAdvide(ジョインポイントポイント、オブジェクトのプロキシ){
//処理ロジック
}

4)ターゲット:着信通知方法の参照のために対象物を。
@Before(「前()&&ターゲット(目標)
公共ボイドbeforeAdvide(ジョインポイントポイント、プロキシオブジェクト){
//処理ロジック
}

5)引数:着信通知処理のためのパラメータ。
@Before( "の前に()&&引数(年齢、ユーザー名)")
公共無効beforeAdvide(ジョインポイントポイント、int型の年齢、文字列のユーザー名){
//処理ロジック
}

6)@within一個の一致するクラス・パラメータは、注釈のタイプを決定するために使用される、すべてのメソッドが一致されます。
@Pointcut( "@ WITHIN(com.cjm.annotation.AdviceAnnotation)")
-すべてのクラスが一致@AdviceAnnotation示されている
(前公共ボイド){}

7)@target:@withinと機能が似ていますが、保持ポリシーを指定する必要があり、アノテーションインタフェースはRUNTIMEです。
@Pointcut( "標的@(com.cjm.annotation.AdviceAnnotation)")
公共ボイド前(){}

8)@args:着信接続点は、Javaクラス指定注釈注釈@argsマーキングすべき対象物に対応します。
@Before( "@引数(com.cjm.annotation.AdviceAnnotation)")
公共ボイドbeforeAdvide(ジョインポイントポイント){
//処理ロジック
}

9)@Annotation:そのパラメータ注釈接続点マッチングによって指定された注釈が付け方法。それは、すべてのメソッドが一致する指定されたノートを注釈が付けられています。
@Pointcut( "注釈@(com.cjm.annotation.AdviceAnnotation)")
公共ボイド前(){}

10)豆:豆接続点によって定義された場合、受信チューブBeanの名前。Spring2.5は、キーワード追加されます。
@Pointcut( "豆(人物)")
公共ボイド前(){}

 

おすすめ

転載: www.cnblogs.com/runnerjack/p/10988165.html