Spring AOP学習

10207 ワード

基礎概念:
うどん(Asppect):公式の抽象的な定義は「一つの注目点のモジュール化で、この注目点は複数のオブジェクトを横断的に切断する可能性がある」ということです.この例では、「切面」とは、TestAspectが注目する具体的な行為の一つです.例えば、AServiceImpl.barA()の呼び出しは、TestAspectが注目する行為の一つです.「うどん」はApplication Contectの中でに配置されています.
接続点(Joinpoint):プログラム実行中のある行為、例えばAServiceImpl.barA()の呼び出しやBServiceImpl.barB(String msg,int type)が異常を投げかけるなどの行為.
通知(Advice):「切面」は、ある「接続点」に対して発生する動作、例えば、TestAsplactでcomp.spring.serviceパッケージの下にあるすべての種類の方法に対してログ記録を行う動作がAdviceです.その中で、一つの「うどん」は、TestAspectなど、複数の「Advice」を含むことができる.
切り込みポイント(Pointcut):接続点に合致するという断言は、AOPで通知され、一つの切り込み点表現と関連があります.例えば、TestAsplactにおけるすべての通知の注目される接続点は、切入点式execution(*comp.spring.service.*(.)によって決定される.
1.AOP(Asppect Orient Prograamming)は、切断面向けにプログラミングされています.オブジェクト指向プログラミング(OOP)は、プログラム構造を静的な観点から考えるものであることが理解される.
切断面向けプログラミング(AOP)は、プログラムの実行過程をダイナミックな観点から考えるものです.
2.SpringにおけるAOPの実現
Springには切込み点と強調処理を定義する二つの選択があります.
a.Annotationの「ゼロ構成」方式に基づいて、@Asppect、@PointcutなどのAnnotationを使って、切り口と強調処理を表示します.
b.XMLプロファイルに基づく管理方式:Springプロファイルを使用して、切込み点と強調点を定義する.
私たちは一般的にXMLの配置で管理しています.以下のとおりです
接麺類:

/**
 *   
 *
 */
public class TestAspect {

    public void doAfter(JoinPoint jp) {
        System.out.println("log Ending method: "
                + jp.getTarget().getClass().getName() + "."
                + jp.getSignature().getName());
    }

    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long time = System.currentTimeMillis();
        Object retVal = pjp.proceed();
        time = System.currentTimeMillis() - time;
        System.out.println("process time: " + time + " ms");
        return retVal;
    }

    public void doBefore(JoinPoint jp) {
        System.out.println("log Begining method: "
                + jp.getTarget().getClass().getName() + "."
                + jp.getSignature().getName());
    }

    public void doThrowing(JoinPoint jp, Throwable ex) {
        System.out.println("method " + jp.getTarget().getClass().getName()
                + "." + jp.getSignature().getName() + " throw exception");
        System.out.println(ex.getMessage());
    }

    private void sendEx(String ex) {
        //TODO          
    }
}


package com.spring.service;
/**
 *   A
 */
public interface AService {
    
    public void fooA(String _msg);

    public void barA();
}

package com.spring.service;
/**
 *  A    
 */
public class AServiceImpl implements AService {

    public void barA() {
        System.out.println("AServiceImpl.barA()");
    }

    public void fooA(String _msg) {
        System.out.println("AServiceImpl.fooA(msg:"+_msg+")");
    }
}

package com.spring.service;

/**
 *   Service B
 */
public class BServiceImpl {

    public void barB(String _msg, int _type) {
        System.out.println("BServiceImpl.barB(msg:"+_msg+" type:"+_type+")");
        if(_type == 1)
            throw new IllegalArgumentException("    ");
    }

    public void fooB() {
        System.out.println("BServiceImpl.fooB()");
    }

}
設定ファイル

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
    default-autowire="autodetect">
    <aop:config>
        <aop:aspect id="TestAspect" ref="aspectBean">
            <!--  com.spring.service             -->
            <aop:pointcut id="businessService"
                expression="execution(* com.spring.service.*.*(..))" />
            <!-- pointcut-ref       Bean id  method      -->
            <!--<aop:before pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="authority" />         -->
            <aop:before pointcut-ref="businessService" method="doBefore"/>
            <aop:after pointcut-ref="businessService" method="doAfter"/>
            <aop:around pointcut-ref="businessService" method="doAround"/>
            <aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>
        </aop:aspect>
    </aop:config>
    
    <bean id="aspectBean" class="com.spring.aop.TestAspect" />
    <bean id="aService" class="com.spring.service.AServiceImpl"></bean>
    <bean id="bService" class="com.spring.service.BServiceImpl"></bean>

</beans>
テストクラスAOPTTest

public class AOPTest extends AbstractDependencyInjectionSpringContextTests {
	
	private AService aService;
	
	private BServiceImpl bService;
	
	protected String[] getConfigLocations() {
		String[] configs = new String[] { "/applicationContext.xml"};
		return configs;
	}
	
	
	/**
	 *       
	 */
	public void testCall()
	{
		System.out.println("SpringTest JUnit test");
		aService.fooA("JUnit test fooA");
		aService.barA();
		bService.fooB();
		bService.barB("JUnit test barB",0);
	}
	
	/**
	 *   After-Throwing
	 */
	public void testThrow()
	{
		try {
			bService.barB("JUnit call barB",1);
		} catch (IllegalArgumentException e) {
			
		}
	}
	
	public void setAService(AService service) {
		aService = service;
	}
	
	public void setBService(BServiceImpl service) {
		bService = service;
	}
}
運転結果は以下の通りです.

log Begining method: com.spring.service.AServiceImpl.fooA
AServiceImpl.fooA(msg:JUnit test fooA)
log Ending method: com.spring.service.AServiceImpl.fooA
process time: 0 ms
log Begining method: com.spring.service.AServiceImpl.barA
AServiceImpl.barA()
log Ending method: com.spring.service.AServiceImpl.barA
process time: 0 ms
log Begining method: com.spring.service.BServiceImpl.fooB
BServiceImpl.fooB()
log Ending method: com.spring.service.BServiceImpl.fooB
process time: 0 ms
log Begining method: com.spring.service.BServiceImpl.barB
BServiceImpl.barB(msg:JUnit test barB type:0)
log Ending method: com.spring.service.BServiceImpl.barB
process time: 0 ms

log Begining method: com.spring.service.BServiceImpl.barB
BServiceImpl.barB(msg:JUnit call barB type:1)
log Ending method: com.spring.service.BServiceImpl.barB
method com.spring.service.BServiceImpl.barB throw exception
    
「Spring参考マニュアル」では、以下のAOPの重要な概念を定義しています.以上のコードを組み合わせて、次のように分析しています.
ターゲットオブジェクト(Target Object):1つ以上のカットで通知されたオブジェクト.例えば、AServcieImplとBServiceImplは、当然ながら実際に実行される場合、Spring AOPはプロキシで実現され、実際のAOPはTarget Objectのプロキシオブジェクトである.
AOPエージェント(AOP Proxy)はSpring AOPにおいて2つの代理方式があり、JDKダイナミックエージェントとCGLOIBエージェントがあります.デフォルトでは、Target Objectがインターフェースを実現した場合、JDKダイナミックエージェント、例えばAServiceImplを採用する.逆に、CGLOIBエージェント、例えばBServiceImplが採用される.CGLOIBエージェントを強制的に使うには、のproxy-targt class属性をtrueに設定する必要があります.
       お知らせ(Advice)タイプ
フロント通知(Before advice):ある接続ポイント(JoinPoint)より前に実行された通知ですが、この通知は接続ポイント前の実行を阻止することができません.Application Conteetでは、の中で要素を使って声明しています.例えば、TestAspectにおけるdoBefore方法
後通知(After advice):ある接続ポイントが終了した時に実行される通知(正常に戻るか、それとも異常終了するかを問わず).Application Comptextでは、の中で要素を使って声明しています.例えば、TestAspectのdoAfter方法ですので、AOPATestでBServiceImpl.barBを呼び出して異常を出した場合、doAfter方法はまだ実行されます.
復帰後の通知(After return advice):ある接続点が正常に完了した後に実行される通知には、例外を除外する場合があります.Apple Conteetでは、要素を使って声明しています.
サラウンド通知(Around advice):一つの接続点を囲む通知は、WebにおけるServlet仕様におけるFilterのdoFilter方法と同様である.メソッドの呼び出しの前後にユーザー定義の行動を完了することもできますし、実行しないことも選択できます.Application Comptextでは、の中で要素を使って声明しています.例えば、TestAspectにおけるdoAsound方法.
異常を投げたら通知(After throwingg advice):方法が異常終了した時に実行する通知.Application Contectでは、の中で要素を使って声明しています.例えば、TestAspectのdoThrowing方法です.
       点式を切り込む
通常は、表式で「execution」を使うと、ほとんどの要件を満たすことができます.

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:方法の操作権限
ret-type-pattern:戻り値
declaring-type-pattern:方法のあるカバン
name-pattern:方法名
parm-pattern:パラメータ名
throws-pattern:異常
ここで、ret-type-patternとname-pattern以外はオプションです.上記の例では、execution(*comp.spring.service.*.*))は、comp.spring.serviceパッケージの下で、戻り値は任意のタイプです.メソッド名は任意です.パラメータは制限されないすべての方法です.
回転:
http://pandonix.iteye.com/blog/336873