Spring AOP(Aspect Oriented Programming)

5671 ワード

1.予測向けのプログラミングとは?


観点向けのプログラミング:いくつかのロジックをコアと追加のロジックに分割し、それぞれモジュール化します.
  • コア観点:コアロジック
  • 追加観点:コアロジックの追加操作(データベース接続、ログ記録、ファイルI/Oなど)
  • を実行する.

    分散された注目点:他のセクションで繰り返し記述されるコード
    ->モジュール化し、重要なビジネスロジックから分離して再利用

    2.AOPに関するコメント


    1. pointcut


    :調査を適用する場所の定義

    1-1. 実行(アクセス制御者/戻り/パッケージを含むクラスパス/パラメータ)


    @Pointcut("execution(public void get*())")
    public戻り値を持たないgetで始まるすべてのメソッドにパラメータが存在しないメソッドに適用
    //*:すべての値
    //.. : 0以上のすべての値
    @Pointcut("execution(* *(..))")
    すべてのアクセス制御者と戻りタイプ
    すべてのパスのクラスを適用
    ...:いくつかのパラメータを実行
    @Pointcut("execution(* com.java.example.study())")
    com.java.EXample classのラーニング()メソッドを呼び出すときに実行
    @Pointcut("execution( com.java...*())")
    ...:パッケージを含むすべてのサブパッケージに適用

    1-2. 内部(クラスパス)


    :パッケージに適用するすべての方法
    @Pointcut("within(com.java.example.*)")
    com.java.exampleサブクラスに適用されるすべてのメソッド

    1-3. bean(bean id)


    :対応するbean idを持つbeanに適用されるすべての方法
    @Pointcut(bean(example))
    exampleというbean idに適用されるすべての方法

    2. Advice


    :コアロジックに反映されるタイミングの決定
    @Advice("pointcut")
    pointcut:メソッドを実行する場合
    Advice:共通コードを実行するタイミング->メソッドの前/後...

    2-1. before


    :メソッド実行前
    @Before("execution(* com.java.example.study())")

    2-2. after


    :メソッドの実行後
    @After("execution(* com.java.example.study())")

    プリセットpointcutインジケータ


    @Pointcut("execution(* com.java.example.study())")
    private void pointcut() {}
    //
    @Before("pointcut()")
    @After("pointcut()")

    2-3. AfterReturning


    :戻ると
    @AfterReturning(value = "pointcut()", returning = "returnValue")
    returnプロパティを使用してメソッドの戻り値をチェックできます.

    2-4. AfterThrowing


    :例外が放出された時点
    @AfterThrowing(value = "pointcut()", throwing = "exception")
    duppingプロパティを使用してメソッドの例外をチェックおよび有効にします.

    2-5. Around


    :メソッドを呼び出すプロセス全体
    @Component
    @Aspect
    public class LogAspect {
        
        Logger logger = LoggerFactory.getLogger(LogAspect.class);
        
        @Around("execution(* com.java.example.study())")
        public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            
            // 메소드를 실행
            Object proceed = joinPoint.proceed();
            
            stopWatch.stop();
            logger.info(stopWatch.prettyPrint());
            
            return proceed; // 결과 리턴
        }
    }
    
    @Aspect:classが付加機能classであることを通知するためのコメント
    @Component:spring beanとして登録(Spring beanのみ)
    ProceedingJoinPoint interface
  • getSignature():呼び出しメソッドの情報を取得する
  • getTarget():ターゲットオブジェクトを解く
  • getArgs():パラメータリスト
  • を取得
  • 続行():ターゲットメソッド
  • を実行

    3.注釈に基づくAOP


    1.機能を追加する方法にコメントを追加

    @LogExecutionTime
    public void exampleMethod() {
    	...
    }

    2.コメントの定義

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LogExecutionTime {
    }
    @Target(ElementType.METHOD):メソッドにコメントを使用
    @Reention(保存ポリシー.RUNTIME):実行時までコメントを保持

    3.Asspectクラスの作成

    @Component
    @Aspect
    public class LogAspect {
        
        Logger logger = LoggerFactory.getLogger(LogAspect.class);
        
        @Around("@annotation(LogExecutionTime)")
        public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            
            // 메소드를 실행
            Object proceed = joinPoint.proceed();
            
            stopWatch.stop();
            logger.info(stopWatch.prettyPrint());
            
            return proceed; // 결과 리턴
        }
    }

    4. Proxy pattern


    ビジネスロジックの中間にソースコードを挿入します。

  • Source Code -> ByteCode
    :ソースコードがバイトコードとなった場合、コード注入
  • ByteCode -> Class Load
    :ByteCodeをメモリに注入するとき
  • Proxy Pattern
  • SpringはAOP 3を実施する。ProxyPatternの使用


    Proxy Patternの構造とストリーム


  • クライアントは、Proxy呼び出し
  • ではなく、関数を直接呼び出します.
  • Proxyクラスから実クラス
  • を呼び出す.
    は、
  • クライアント
  • を返します.
    @Service
    public class TestEventService implements EventService {
        @override
        public void createEvent() {
        	System.out.println("create event");
        }
        
        @override
        public void publishEvent() {
        	System.out.println("create event");
        }
    }
    @Primary
    @Service
    public class ProxyTestEventService implements EventService {
    
        @Autowired
        TestEventService testEventService;
        
        @override
        public void createEvent() {
        	long begin = system.currentTimeMillis();
        	testEventService.createEvent();
            system.out.println(system.currentTimeMillis()-begin);
        }
        
        @override
        public void publishEvent() {
        	long begin = system.currentTimeMillis();
        	testEventService.createEvent();
            system.out.println(system.currentTimeMillis()-begin);
        }
    }
    @Primary:プリファレンス
    ->クライアントがEventServiceでメソッドを呼び出すと、プロキシオブジェクトが呼び出されます.
    @Service:クラスをルートコンテナのbeanオブジェクトとして作成

    Spring AOP Proxy Pattern

  • JDK Dynamic Proxy
  • CGlib Proxy