、春AOP工場
1.通知がない場合にはAdvisedSupportカスタム設定、デフォルトのJDKの動的プロキシ
2. AdvisedSupportが設定されている場合、エージェントクラスであると判定されたインターフェイス、JDKの動的プロキシを使用してインターフェイス、そうでなければ、ダイナミックプロキシーCGLIBありません
3. JDK動的プロキシとCGLIB動的プロキシは、MethodInterceptorのチェーンAdvisedSupportの実装に基づいています
@Override 公共 AopProxy createAopProxy(AdvisedSupportの設定)がスローAopConfigException { 場合(config.isOptimize()|| config.isProxyTargetClass()|| hasNoUserSuppliedProxyInterfaces(設定)){ クラス targetClass = <?> config.getTargetClass(); もし(targetClass == NULL ){ スロー 新しい(「TargetSourceがターゲットクラスを決定することはできません:」+ AopConfigExceptionを 「インタフェースまたはターゲットがプロキシの作成に必要とされます」)。 } であれば(targetClass.isInterface()){ 返す 新しいJdkDynamicAopProxy(設定)。 } 戻り 新しいObjenesisCglibAopProxy(設定します)。 } 他{ 戻り 新しいJdkDynamicAopProxy(設定します)。 } }
第二に、AOP JDKの動的プロキシに基づいて、()メソッドをのInvocationHandlerインタフェースの呼び出し呼び出しを達成するために行きます
メソッドインターセプタチェーン鎖MethodInterceptorの記載AdvisedSupportを取得する1スプリング
2.チェーンは、元のメソッドを呼び出すための直接反射空の場合
3.そうでない場合、コールは()メソッドを進むが、この方法は、再帰的な方法であります
@Override パブリックオブジェクトを呼び出し(オブジェクトプロキシ、方法方法、[]引数オブジェクト)スローのThrowable { MethodInvocation呼び出しを、 オブジェクトoldProxy = nullを。 ブール setProxyContext = 偽; TargetSource targetSource = この.advised.targetSource。 クラス <?> targetClass = nullを。 オブジェクトのターゲット = nullを。 試す{ あれば!(この .equalsDefined &&AopUtils.isEqualsMethod(メソッド)){ // ターゲットに等しいを実装していない(Object)メソッド自体。 リターンは等しい(引数[0 ])。 } もし(!この .hashCodeDefined && AopUtils.isHashCodeMethod(メソッド)){ // ターゲットはハッシュコード()メソッド自体を実装していません。 返すのhashCode()を。 } もし(!この .advised.opaque && method.getDeclaringClass()。isInterface()&& method.getDeclaringClass()。isAssignableFrom(助言した。クラス)){ //プロキシ設定とProxyConfigでのサービス呼び出しが... 返す AopUtils.invokeJoinpointUsingReflectionを(これは、メソッド、引数を.advised)。 } オブジェクトRETVAL。 場合(この.advised.exposeProxy){ // 必要に応じて呼び出しを使用可能にします。 oldProxy = AopContext.setCurrentProxy(プロキシ)。 setProxyContext = 真; } // nullになることがあります。私たちは、「自分」の目標は、時間最小限に抑えるためにできるだけ遅く取得する // 場合には、それはプールから来ています。 ターゲット=targetSource.getTarget(); もし(!ターゲット= ヌル){ targetClass = target.getClass(); } // このメソッドの傍受チェーンを取得します。 リスト<OBJECT>チェーン= この.advised.getInterceptorsAndDynamicInterceptionAdvice(方法targetClass)。 // 私たちはどんなアドバイスを持っているかどうかを確認してください。もしそうしないと、私たちは直接にフォールバックすることができます // ターゲットの反射呼び出し、およびMethodInvocationを作成しないように。 もし(chain.isEmpty()){ //私たちはMethodInvocationの作成をスキップすることができます:ちょうど直接ターゲットを呼び出す // 我々はそれがないん知っているので、最終的な呼び出しがInvokerInterceptorなければならないことに注意してください // ターゲットで反射操作は何も、ノーホットスワップや空想プロキシを。 RETVAL = AopUtils.invokeJoinpointUsingReflection(ターゲット、メソッド、引数)。 } 他{ // 私たちは、メソッド呼び出しを作成する必要があります... 呼び出し= 新しいReflectiveMethodInvocation(プロキシ、目標、方法、引数、targetClass、チェーン)。 // インターセプタチェーンを通じてジョインポイントに進みます。 RETVAL = invocation.proceed()。 } // マッサージの戻り値は必要に応じて。 クラス戻り値の= <?> method.getReturnType(); もし(!RETVAL = nullを && RETVAL ==ターゲット&& returnType.isInstance(プロキシ)&& !。RawTargetAccess クラス.isAssignableFrom(method.getDeclaringClass())){ // 特殊なケース:それは"この"を返され、戻り値の型メソッド //は型の互換性があります。ターゲットが設定した場合、我々は助けることができないことに注意してください // 別の返されたオブジェクト内の自身への参照を。 RETVAL = プロキシ。 } それ以外の 場合(RETVAL == nullの &&戻り値の= Void.TYPE &&!returnType.isPrimitive()){ スロー 新しい(AopInvocationExceptionを "アドバイスからヌル戻り値がプリミティブのための戻り値の型と一致していません:" + メソッド)。 } 戻り値のretval; } 最後に{ 場合(目標!= nullの &&!targetSource.isStatic()){ //はTargetSourceから来ている必要があります。 targetSource.releaseTarget(ターゲット) } 場合(setProxyContextは){ // 古いプロキシを復元します。 AopContext.setCurrentProxy(oldProxy)。 } } }
第三に、AOP CGLIB動的プロキシに基づいて、またベースAdvisedSupport傍受するためにコールバックを()メソッドを実装します
プライベートコールバック[] getCallbacks(<?>クラスはrootClass)スロー例外{ // 最適化の選択肢のために使用されるパラメータ... ブール exposeProxy = この.advised.isExposeProxyを(); ブール isFrozen = この.advised.isFrozen()。 ブール isStatic = この.advised.getTargetSource()isStatic()。 // (AOP呼び出すために使用される)、「AOP」インターセプタを選択してください。 コールバックaopInterceptor = 新しい DynamicAdvisedInterceptor(これは.advised)。 .............. }
第四に、再帰的なインターセプタチェーン
1.すべてのインターセプタは、そうでない場合は再帰呼び出しインターセプター、それは真のガードと呼ばれる、オーバー実行されています
2.迎撃する前に、最初に行った後、前に進んで行って、インターセプタのチェーンの最後のリンクです
3.迎撃した後、実行後の最初の実行が再び進みます
参考:
https://www.cnblogs.com/kevin-yuan/p/5571200.html
https://blog.csdn.net/u012707422/article/details/93894174
https://blog.csdn.net/u011983531/article/details/80359304
https://www.jianshu.com/p/012f950206ca