SpringシリーズAOP使用

6570 ワード

AOP紹介
オブジェクト向けの方法でコードをうまく整理したり、継承したりしてコード再利用を実現したりすることができます.しかし、プロジェクトには常に重複するコードが表示され、汎用ログ印刷、トランザクション、セキュリティチェックなど、継承方式で再利用管理するのは容易ではありません.これらのコードをカプセル化して汎用モジュールにすることができますが、コード内の必要な場所ごとに表示呼び出しを行う必要があり、使いにくいです.これはAOPを利用する時です.
AOPは1種のプログラミングの範式で、特定の問題を解決するために用いて、すべての問題を解決することができなくて、OOPの補充と見なすことができて、よくあるプログラミングの範式はあります:
  • プロセスプログラミング向け;
  • オブジェクト向けプログラミング;
  • 関数プログラミング(関数プログラミング);
  • イベント駆動プログラミング(GUI開発で比較的一般的);
  • フェースプログラミング
  • AOPの一般的な使用シーン
  • 性能モニタリング、方法呼び出し前後に呼び出し時間を記録し、方法は長すぎるかタイムアウト警報を実行する.
  • キャッシュエージェントは、あるメソッドの戻り値をキャッシュし、次回このメソッドを実行すると、キャッシュから直接取得します.
  • ソフトウェアは解読して、AOPを使ってソフトウェアの検証類の判断ロジックを修正します;
  • ログを記録し、方法実行前後にシステムログを記録する.
  • ワークフローシステム、ワークフローシステムは業務コードとプロセスエンジンコードを混合して実行する必要があり、AOPを使用してそれを分離し、動的に業務を停止することができる.
  • 権限検証、方法実行前に現在の方法を実行する権限があるかどうかを検証し、ない場合は権限がない異常を投げ出し、業務コードによって捕捉する.
  • トランザクション.

  • Spring AOP関連概念
  • AOP:このような実行時(またはコンパイル時またはロード時)、動的にいくつかの共通コードをクラスの指定方法、指定位置に切り込むプログラミング思想は接面向けのプログラミングである;
  • 切面(Aspect):A modularization of a concern that cuts across multiple classes.Springで切面は@AspectJを表記するクラスであり、あまり複雑に考えないでください.
  • 接続点(Joinpoint):メソッドの実行中にある点は、適用の実行中にフェースを挿入できる点です.この点は、メソッドを呼び出すとき、例外を投げ出すとき、フィールドを変更するときでもかまいません.フェースコードは、これらの点を使用してアプリケーションの通常のプロセスに挿入し、新しい動作を追加できます.
  • 通知(advice):切断面がどのような作業を完了するか、およびどの時点で作業を行うかを記述する.
  • Pointcut:接続点のセットを一致させるために使用され、pointcutはadviceに関連付けられ、pointcutが一致する接続点が実行されるとadviceコードが実行されます.
  • Introduction
  • Targetobject:切断面に織り込まれたオブジェクト;
  • AOP proxy:切面コードとtargetコードがパッケージされたオブジェクト、SpringではJDKダイナミックエージェントとCGLIBがサポートされ、デフォルトではJDKダイナミックエージェントが使用されますが、エージェントされたクラスにインタフェースが実装されていない場合、またはユーザーがCGLIBを強制的に使用する場合、SpringはCGLIBエージェントを使用します.
  • Weaving:ターゲットコードにカットコードを追加するプロセスで、織り込みのタイプはコンパイル時織り込み、ロード時織り込み、実行時織り込み(Springは実行時織り込み)
  • があります.
    SpringAOPでは、5種類の通知を適用できます.
  • 先行通知(Before):ターゲットメソッドが呼び出される前に通知機能が呼び出されます.
  • 後置通知(After):宛先メソッドが完了した後に通知を呼び出すが、メソッドの出力が何であるかは気にしない.(実行が成功するかどうかにかかわらず実行する)
  • .
  • リターン通知(After-returning):ターゲットメソッドが正常に実行された後に通知が呼び出されます.
  • 異常通知(After-throwing):ターゲットメソッドが異常を投げ出した後に通知を呼び出す.
  • 周回通知(Around):通知が通知されたメソッドを包むことを通知し、通知されたメソッドが呼び出される前と呼び出された後にカスタムの動作を実行する.
  • Spring AOP関連
    Aopを開く
    
    //       AOP  
    //  xml    :
    
    //exposeProxy = true     true,            expose AopContext ThreadLocal  
    //    AopContext.currentProxy();           。
    
    //proxyTargetClass          JDK        CGlib  ,   true   CGlib  ,false     JDK    
    
    //  :    Spring Boot  ,          。AopAutoConfiguration               AOP
    //    CGLIB    ,Spring Boot             
    
    @Configuration
    @EnableAspectJAutoProxy(exposeProxy = true,proxyTargetClass = false)
    public class AopConfig {
    
    }
    
    
    

    従来の構成であれば、以下の構成でAOP機能をオンにすることができます.
    
    

    Aspectを定義
    Aspects (classes annotated with @Aspect) can have methods and fields, the same as any other class. They can also contain pointcut, advice, and introduction (inter-type) declarations.
    通常のBeanの定義方法、または@Aspect注記を付けて定義できます.クラスがフェースクラスとしてマークされると、他のフェースの代理オブジェクトにはなりません.
    PointCutの定義
    接面式は、インジケータ、ワイルドカード、演算子で構成できます.
  • インジケータ(Designators)
  • マッチングメソッドexecution()
  • マッチング注記@target()@args()@within()@annotation()
  • マッチングパッケージ/タイプwithin()
  • マッチングオブジェクトthis()bean()target()
  • マッチングパラメータargs()
  • Wildcards(ワイルドカード)
  • *任意の数の文字に一致する
  • +一致指定クラスおよびそのサブクラス
  • .. 一般的に任意のパラメータに一致するサブパッケージまたはパラメータ
  • Operators(演算子)
  • &&オペレータ
  • ‖またはオペレータ
  • ! 非オペレータ
  • 次に、PointCutを定義する例を示します.
    package com.csx.demo.spring.boot.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    @Aspect
    public class MyAspect {
    
        //PointCut        Spring bean   
        //Pointcut              && ||  !       .
        //               && ||  
    
        private static Logger logger = LoggerFactory.getLogger(MyAspect.class);
    
        //*:               
        //       controller       echo  ,         
        @Pointcut("execution(* com.csx.demo.spring.boot.controller.*.echo(..))")
        public void pointCut1(){}
    
        //  echo                      
        @Pointcut("execution(* com.csx.demo.spring.boot.controller.*.echo(*))")
        public  void pointCut2(){}
    
        //  echo         ,       ,        String
        @Pointcut("execution(* com.csx.demo.spring.boot.controller.*.echo(*,String))")
        public void pointCut3(){}
    
        //contrller                
        //      with @with        
        @Pointcut("within(com.csx.demo.spring.boot.controller..*)")
        public void pointCut4(){}
    
        //  RestController              
        @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
        public void pointCut5(){}
    
        //   @Within  
        @Pointcut("@target(org.springframework.web.bind.annotation.RestController)")
        public void pointCut10(){}
    
        //MyService            
        //  MyService      ,             
        @Pointcut("this(com.csx.demo.spring.boot.service.MyService)")
        public void pointCut6(){}
    
        @Pointcut("this(com.csx.demo.spring.boot.service.MyServiceImpl)")
        public void pointCut7(){}
    
        //  bean       
        @Pointcut("bean(myServiceImpl)")
        public void pointCut8(){}
    
        //@within @target      ,@annotation        
        //      GetMaping     
        @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
        public void pointCut9(){}
    
        //        ,     String   
        @Pointcut("args(String)")
        public void pointCut11(){}
    
    
        @Before("pointCut1()")
        public void befor(){
            logger.info("    vvvv...");
            logger.info("      ...");
        }
    
        @After("pointCut1()")
        public void after(){
            logger.info("    ");
        }
    
        @AfterReturning("pointCut1()")
        public void afterReturn(){
           logger.info("    ");
        }
    
         //             
        @AfterThrowing("pointCut1()")
        public void afterThrowing(){
            logger.info("    ");
        }
    
        @Around("pointCut1()")
        public void around(ProceedingJoinPoint point) throws Throwable {
            logger.info("    ...");
            logger.info("      ...");
            point.proceed();
            logger.info("      ");
        }
    
    }