AOPスプリングソースコード解析

新の場合に達成例1つのAOP

public class TraceTest {

    public static void main(String args[]) {
        TraceTest test = new TraceTest();
        test.rpcCall();
    }

    // 虽然 intellij 没有给出提示,但是这个 Trace 还是成功的
    @Trace
    public void rpcCall() {
        System.out.println("call rpc");
    }

}

@Aspect
public class TraceAspect {
    @Pointcut("@annotation(Trace)")
    public void tracePointcutDefinition() {}

    @Around("@annotation(Trace) && execution(* *(..))")
    public Object aroundTrace(ProceedingJoinPoint pjp) throws Throwable {
        Object returnObj = null;

        try {
            System.out.println("before traced method started...");
            returnObj = pjp.proceed();

        } catch (Throwable throwable) {
            throw throwable;
        } finally {
            System.out.println("after traced method executed...");
        }

        return returnObj;
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Trace {
}

//before traced method started...
//call rpc
//after traced method executed...

コンテナが自動的に生成されたプロキシクラスに必要なコードを挿入しますが、直接、上記の例から、我々は例を新しいが、この例では、新しい外でてきたので、通常使用春AOPは、コンテナを注入するために必要とされますコードに織り込まれ、それはそれを達成する方法ですか?

コンパイルとAOPの注入を実行すると、上記の例では、変更後にすでに.classファイルをその結果、注射が終了してコンパイルされており、容器の使用を必要としない、見た目のポンポンを配置し

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.7</version>
    <configuration>
        <complianceLevel>1.8</complianceLevel>
        <source>1.8</source>
        <target>1.8</target>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>


public void rpcCall();
  Code:
     0: getstatic     #46                 // Field ajc$tjp_0:Lorg/aspectj/lang/JoinPoint$StaticPart;
     3: aload_0
     4: aload_0
     5: invokestatic  #52                 // Method org/aspectj/runtime/reflect/Factory.makeJP:(Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
     8: astore_1
     9: aload_0
    10: aload_1
    11: invokestatic  #71                 // Method aspectjaop/annotation/TraceAspect.aspectOf:()Laspectjaop/annotation/TraceAspect;
    14: aload_1
    15: checkcast     #59                 // class org/aspectj/lang/ProceedingJoinPoint
    18: invokestatic  #75                 // Method rpcCall_aroundBody1$advice:(Laspectjaop/annotation/TraceTest;Lorg/aspectj/lang/JoinPoint;Laspectjaop/annotation/TraceAspect;Lorg/aspectj/lang/ProceedingJoinPoint;)Ljava/lang/Object;
    21: pop
    22: return

だから、MavenのAspectJのAOPの方法で生成された.classファイル、織り込ま時間をコンパイルしますプラグインコード

春AOP 2例

私たちは、春AOPことを勉強する必要があります

public class Logging {
    public void beforeAdvice() {
        System.out.println("Going to setup student profile.");
    }

    public void afterAdvice() {
        System.out.println("Student profile has been setup.");
    }

    public void afterReturningAdvice(Object retVal) {
        System.out.println("Returning returning advice ***** :");
    }

    public void AfterThrowingAdvice(IllegalArgumentException ex) {
        System.out.println("There has been an exception: " + ex.toString());
    }
}

public class Student {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void ExceptionRaised() {
        System.out.println("this is exception message ");
    }
}


public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean.xml");

        Student student = (Student) context.getBean("student");

        student.getName();
        student.getAge();

        student.ExceptionRaised();
    }
}
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.3.4.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.10</version>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.10</version>
</dependency>

最初の例では、aspectjweaverを必要としませんが、2番目の例では避けられませんでした。春のコンテキストは、射出工程を開催しますので、必要AspectJの-のmaven-pluginのが、第二の例の最初の例が必要とされていない、春の後続の章春AOPの実装方法の例を分析するために使用され、研究を支援(実施例2)コードであります

のは、アプリケーションプロセスのAOPを分析してみましょう。ケースは、インタフェースのコードタイプに織り込まれていないため、エージェントは動的ではなくJdkDynamicProxy CGLIBべき

分析のためのエントリポイントがgetProxyの関数で、関数の本体にブレークポイントを入れて、getProxy機能のCGLIBを知って、リターン機能によれば、コールスタック全体を知ることができる、コールスタックものスレッドスタックのIntelliJアイデアから直接見つけることができます。

AbstractAutowireCapableBeanFactory.doCreateBean()
AbstractAutowireCapableBeanFactory.initializeBean()
AbstractAutowireCapableBeanFactory.postProcessBeforeInitialization()
AbstractAutowireCapableBeanFactory.postProcessAfterInitialization()
    AbstractAdvisorAutoProxyCreator.createProxy
        DefaultAopProxyFactory.createAopProxy // 这里选择 JdkDynamicProxy 或者 CGLibProxy
            createProxy// 根据具体选取的 AOP proxy 构造代理实例

上記の薬剤から、次はいくつかのポイントをクリアすることができます。

  1. それは、コード後処理を注入された場合に豆を生成するごとに、チェックする必要があります。BeanのAbstractAdvisorAutoProxyCreator.findElibleAdvisorの位置を確認し、サブクラスポストプロセッサの多くを達成するためにリスト顧問、顧問を返さ
  2. アスペクト定義はAdvisorは二つの部分に分け、AspectJPointcutAdvisorに変換され、第1の部分が第2の部分は、ポイントカットアドバイス、アドバイスノート部分であり、AspectJPointcutAdvisorポイントカットと呼ばれるサブタイプを含むポイントカットせずにそのインターフェイスアドバイザーで唯一のアドバイスは、指摘しました。各注釈は、そのような方法のものとアドバイザ、アドバイザポイントカットがコンテンツを注釈され、その機能はアドバイス部を達成することで、基準方法の機能を達成するために、生成LoggingServiceのをアドバイスすることです
  3. JdkDynamicProxyはのInvocationHandlerとAopProxyのサブクラス、そのメンバ変数AdvisedSupportので、ビーンJdkDynamicProxyの対応する各インスタンスであります
  4. アドバイザ保持アドバイス(関節時点で実行するアクション、およびアドバイスの能力を決定するフィルタ)
  5. ポイントカットは、クラスフィルタ及び方法マッチングの構成されています
  6. ReflectiveInterceptor.proceed。かどうかjdkDynamic CGLIBはMethodInterceptorのに変換され、

場所が残っていたときに理解していないコードを見てください

  1. なぜ、なぜ、これを保存することはできません?BeanDefinitionべきかBeanDefinitionは、具体的な実装によって提供されるプロパティ値は、コンストラクタの引数の値、および更なる情報を持っているBeanインスタンスを、説明しています。

実際にCGLIBは、動的プロキシを構築するあまり分析せずに、まだかなり簡単な方法です。JdkDynamicProxy工法はやや複雑であるので、それは顧問とラインのセットエンハンサーの様々な様々なを見つけることですが、一方で、JdkDynamicProxyはもっと複雑。まず、JdkDynamicProxyはadvisedSupportを使用する必要があり、顧問を記入し、targetClass、その後の内側JdkDynamicProxyはのInvocationHandlerを継承しました

オリジナル:ビッグボックス  AOP春のソースコード解析


おすすめ

転載: www.cnblogs.com/chinatrump/p/11612106.html