AOP(切断面向けプログラミング)シリーズの一つ(spring xml配置方式)

12190 ワード

AOP(切断面向けプログラミング)シリーズの一つjava (annotation)に接続され、注釈はメタデータであり、自身は業務処理能力を備えていない.AOPプログラミングは実際の処理能力を注釈する一般的な方法です.
A OPは何ですか
AOPはAspect Oriented Prograammingの略称で、普通は に訳します.AOPと言えば、まだ知らない人がいるかもしれませんが、まず一人でよく知っているOOP(Object-orented programming、対象プログラムに向かって設計します).現実的な事物を抽象的にプログラム対象とするプログラミング思想は、ソフトウェアの再使用性、柔軟性、拡張性を大いに高め、ソフトウェア開発分野に広く応用されている.AOPとは、プリコンパイル方式と実行期間の動的エージェントにより、ソースコードを修正しない場合に、プログラムの動的統一に機能を追加できる技術であり、目的はコーディネーターと被コーディネーターの間の結合であり、コードの柔軟性と拡張性を高めることである.だから、OOPの代わりにAOPが使われているという話はまったくでたらめです.二つの適用シーンと設計の目標は違っています.一般的には、AOPはプログラムのコンパイルプロセスまたは実行プロセス(動的エージェント)において、事前に設定された切断面に従って、特定の機能を統一的に追加し、業務コードに侵入または低侵入がないということです.
よくあるAOP使用シーン
現在よく見られる応用シーンは主にログ記録、性能統計、セキュリティコントロール、事務処理、異常処理などです.特にプログラミングフレームの中で最も一般的です.
spring XML配置方式AOPTalk is cheap, just show you the code本明細書ではAOPを使用して、Aspring XML構成を使用しています.AspecJ注釈は使用しません.
接面用の注解java (annotation)のカスタムコメントを借りる.AnnotationDemo(ただ怠けるだけ).注解は上記で説明されています.
package com.hxx.annotation;

import com.hxx.enums.UserType;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AnnotationDemo {
    long time() default 0;

    int count() default 0;

    String name() default "XiaoMing";

    UserType userType() default UserType.SYSTEM_ADMIN;

}
面切り方法の定義
ここでは、切面トリガの特定のロジックを指します.文字の説明が苦手なので、コードを見てください.
package com.hxx.aop;

import com.hxx.annotation.AnnotationDemo;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * 
 */
public class SpringAspect {
    /**
     *           
     *
     * @param point
     */
    public void doBefore(JoinPoint point) {
        System.out.println("---------------> before ");
    }

    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        System.out.println("---------------> around start");
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        AnnotationDemo annotation = methodSignature.getMethod().getAnnotation(AnnotationDemo.class);
        System.out.println("annotation ---------------> " + annotation);
        Object proceed = null;
        try {
            proceed = point.proceed();
        } catch (Throwable throwable) {
            throw throwable;
        }
        System.out.println("---------------> around end");
        return proceed;
    }

    /**
     *           
     *
     * @param point
     */
    public void doAfter(JoinPoint point) {
        System.out.println("---------------> after");
    }

    /**
     *       :           ,         ,                  
     *
     * @param point
     */
    public void afterThrowing(JoinPoint point, Throwable throwable) {
        System.out.println("---------------> afterThrowing");
        System.out.println(throwable.getMessage());
    }

    /**
     *
     * @param point
     * @param returnValue
     */
    public void afterReturning(JoinPoint point, int returnValue) {
        System.out.println("---------------> afterReturning +++ " + returnValue);
    }
}

AsppectJではなく、一つも使わないと言っています.AsppectJで注釈はしていませんが、aspectjのいくつかのクラスを使っていますので、aspectj依存を導入したいです.本論では、mavenのpomファイルの依存性を例にあげます.jarパッケージのバージョン番号は普通最新版を選択すればいいです.

    org.aspectj
    aspectjrt
    ${aspectj.version}


    org.aspectj
    aspectjweaver
    ${aspectj.version}

これ以外は普通のクラスです.クラスのメソッド名とパラメータ名はspring xmlの配置に使われます.大丈夫ですか?
spring XML配置
spring xml構成を使うなら、まずspring依存を導入しますか?それとも、maven依存だけで、バージョンは自分で選びます.


    org.springframework
    spring-context-support
    ${spring.version}



    org.springframework
    spring-aop
    ${spring.version}

spring context入口ファイル(appication Contect.xml):



    
    
    
    
    
    

メインはaopのxml構成で、その内容はこうです.



    
    
        
            
            
            
            
            
            
        
    

まず、この構成ファイルはaop規則であり、実際の使用では必要に応じて複数のルールが定義されてもよい.proxy-target-classは、クラスベース(CGLOIB)エージェントを作成するかどうかを指定し、デフォルトではjdkプロキシを作成する.trueを選択すればいいです.(この二つの代理店の性能の違いも先に穴を掘ってから記入します.)aop:aspectタグは、断面を定義し、refは、断面の例を指定する.id切断面の表示を設定する.orderは、同じ切り口(接続点)の複数の断面に対して実行順序を指定するために、切面の順序を指定することができます.aop:pointcutタグは、接頭点、すなわち接面実行条件を定義する.IDにロゴを設定し、切り込みポイントを指定して実行する方法に対応する場合に使用します.expressionは接点式を指し、条件に該当する場合は切込み点をトリガします.@annotation(com.hxx.annotation.AnnotationDemo)とはAnnotationDemoに注釈表示されたところに切り込み点(expressionの詳細な解釈、種類及び複合用法も先に穴を掘る)という意味です.aop:aroundタグは、切点の周囲を定義する方法であり、ここでは条件に応じて切点方法を実行することを拒否することができ、プロセス中に発生した異常(飲み込みまたは包装)を処理することもできる.pointcut-refはどの切り込みポイントに属するかを指定し、methodは切面方法名を指定し、本例ではSpringAspectのdoAsound方法である.この時doAsound方法はJoinPointタイプのパラメータしかありません.そうでないと、運転中にパラメータが合わなくてエラーが発生します.aroundで指定した方法では、JoinPointのproceedメソッドを呼び出して切り込みポイントを実行します.アロントもこの過程をめぐって名前がついています.aop:beforeタグは、切り込みポイントが実行される前に実行する方法を定義する.methodは、切断を実行する方法名、すなわちJoinPointのproceed方法の実行前に実行する方法を指定します.aop:afterタグは、切り込みポイントの実行後に実行する方法を定義する.aop:after-throwingラベル定義に異常が発生した場合に実行する方法は、この場合に発生した異常を取得することができますが、例外スローを阻止することができません.throwingはmethodで指定したメソッドに異常なパラメータ名を指定します.throwingの配置があっても、同じ方法で同じ名前のThrowableタイプのパラメータが発生した異常を受信しなければなりません.さもなければ、運転中にパラメータの不一致によってエラーが発生します.aop:after-returningタグ定義は、返却結果の後に実行する方法であり、aop:after-throwingと同様に、リターン値を逆変換する方法で受信することを意味する.設定と方法は同時に現れなければなりません.これらを見てみると、aroundが最も強く、Proceding JoinPointパラメータが切り込みポイントの実行を制御できるので、その使用シーンも一番多いです.JoinPointからは、切り込みポイントの方法及びその注釈情報を入手し、接点の注釈配置を復元することができます.
AOP使用
カット、カットポイントを定義して配置しました.どうやって使うかを確認してみます.まず業務シーンをシミュレートしてインターフェースを定義します.
package com.hxx.api;

/**
 * 
 */

public interface ApiDemo {
    /**
     *         
     *
     * @param input   
     * @return   
     */
    int work(int input);
}

このインターフェースを簡単に実現して、配置されたAOPを使ってください.
package com.hxx.api.impl;

import com.hxx.annotation.AnnotationDemo;
import com.hxx.api.ApiDemo;
import com.hxx.enums.UserType;

import org.springframework.stereotype.Service;

@Service("apiDemo")
public class ApiDemoImpl implements ApiDemo {

    @AnnotationDemo(time = 1, count = 2, name = "admin", userType = UserType.SYSTEM_ADMIN)
    public int work(int input) {
        System.out.println("------->> ApiDemo work");
        return 3 / input;
    }

}

使用は非常に簡単で、方法に注釈を追加すればいいです.業務には全く侵入していません.
結果テスト
junnitのテストケースを使ってテストを行います.
package com.hxx.api;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class) //  junit4    
@ContextConfiguration(locations = {"classpath*:applicationContext.xml"}) //      
public class ApiDemoTest {

    @Resource(name = "apiDemo")
    private ApiDemo apiDemo;

    @Test
    public void testWork() throws Exception {
        apiDemo.work(1);
    }

    @Test
    public void testWorkException() throws Exception {
        apiDemo.work(0);
    }
} 
testWorkを実行すると、結果が得られます.
---------------> around start
annotation ---------------> @com.hxx.annotation.AnnotationDemo(name=admin, count=2, time=1, userType=SYSTEM_ADMIN -      )
---------------> before 
------->> ApiDemo work
---------------> around end
---------------> after
---------------> afterReturning +++ 3
実行結果は予想通りですが、異常が発生した場合はテストされませんでした.testWork Exceptionを実行します.
---------------> around start
annotation ---------------> @com.hxx.annotation.AnnotationDemo(name=admin, count=2, time=1, userType=SYSTEM_ADMIN -      )
---------------> before 
------->> ApiDemo work
---------------> after
---------------> afterThrowing
/ by zero

java.lang.ArithmeticException: / by zero
    at com.hxx.api.impl.ApiDemoImpl.work(ApiDemoImpl.java:15)
    ……
異常が発生し、aroundに飲み込まれていない場合は、after Throwingが実行され、afterも実行されましたが、afterReturningは再実行できません.aroundに異常が発生したステートメントは再実行できません.もしaroundで異常を飲み込んだら、Spring AspectのdoAsound方法を修正します.
 public Object doAround(ProceedingJoinPoint point) throws Throwable {
        System.out.println("---------------> around start");
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        AnnotationDemo annotation = methodSignature.getMethod().getAnnotation(AnnotationDemo.class);
        System.out.println("annotation ---------------> " + annotation);
        Object proceed = 0;
        try {
            proceed = point.proceed();
        } catch (Throwable throwable) {
           // throw throwable;
        }
        System.out.println("---------------> around end");
        return proceed;
    }
testWork Exceptionを再実行して結果を得ました.
---------------> around start
annotation ---------------> @com.hxx.annotation.AnnotationDemo(name=admin, count=2, time=1, userType=SYSTEM_ADMIN -      )
---------------> before 
------->> ApiDemo work
---------------> around end
---------------> after
---------------> afterReturning +++ 0
これにより、aroundで異常を飲み込んで、デフォルトの戻り値を返すことができます.