English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Spring AOP AspectJアノテーション例

SpringフレームワークSpringに基づくものを使用することをお勧めします。 1.2旧スタイルDTDのAOP実装上で使用 Spring AspectJ AOP実装使いやすい。

Spring AOP AspectJ実装を使用する方法は2種類あります:

アノテーションで: ここで学びます。 XML設定(パターンに基づいて): 次のページでそれについて学びます。

注意: aopの概念やその利点などについて学びたい場合は、こちらを訪れてください。AOP概念チュートリアル

Spring AspectJ AOP実装は多くのアノテーションを提供しています:

@Aspect このクラスをアスペクトとして宣言します。 @Pointcut ポイントカット表現を宣言します。

アドバイスを作成するために使用されるアノテーションは以下の通りです:

@Before ビーフォアアドバイスを宣言しました。実際のメソッドを呼び出す前に適用されます。 @After アフターアドバイスを宣言しました。実際のメソッドを呼び出した後に、結果を返す前に適用されます。 @AfterReturning アフターレターンアドバイスを宣言しました。実際のメソッドを呼び出した後に、結果を返す前に適用されます。ただし、アドバイスで結果値を取得することもできます。 @Around アラウンドアドバイスを宣言しました。実際のメソッドを呼び出す前後で適用されます。 @AfterThrowing throwsアドバイスを宣言しました。実際のメソッドが例外を発生させた場合に、このメソッドが適用されます。

ポイントカットを理解する

ポイントカットはSpring AOPの表現言語です。

@Pointcut コメントはポイントカットを定義するために使用されます。ポイントカット表現の名前を参照することもできます。ポイントカット表現の簡単な例を見てみましょう。

@Pointcut("execution(")* Operation.*(..))")
private void doSomething() {}

ポイントカット表現の名前はdoSomething()です。戻り値の型に関係なく、Operationクラスのすべてのメソッドに適用されます。

ポイントカット表現を理解する

以下の例を通じて、ポイントカット表現を試してみましょう。

@Pointcut("execution(public" * *(..))")

それがすべてのpublicメソッドに適用されます。


@Pointcut("execution(public Operation."}*(..))")

それがOperationクラスのすべてのpublicメソッドに適用されます。


@Pointcut("execution(")* Operation.*(..))")

それがOperationクラスのすべてのメソッドに適用されます。


@Pointcut("execution(public Employee.set"*(..))")

それがEmployeeクラスのすべてのpublic設定メソッドに適用されます。


@Pointcut("execution(int Operation."}*(..))")

それは、int値を返すOperationクラスのメソッドに適用されます。


1、@Beforeの例

実際のビジネスロジックメソッドの前にAspectJ Before Adviceを適用します。ここで、変換、認証などの操作を行うことができます。

創建一個包含實際業務邏輯的類。

ファイル: Operation.java

package com.w;3codebox;
public class Operation{
	public void msg(){System.out.println("msg method invoked");}
	public int m(){System.out.println("m method invoked");return 2;}
	public int k(){System.out.println("k method invoked");return 3;}
}

今、アドバイスの前に含まれる側面クラスを作成します。

ファイル: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
	@Pointcut("execution(")* Operation.*(..))")
	public void k(){}//ポイントカット名
	@Before("k()")//before通知に切り口を適用します
	public void myadvice(JoinPoint jp)//it is advice (before advice)
	{
		System.out.println("additional concern");
		//System.out.println("メソッドシグネチャ: " + "Method Signature: ");  + jp.getSignature());
	}
}

applicationContext.xmlファイルにbeanの定義を作成します。

ファイル: applicationContext.xml

<?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.xsd 
	   http://www.springframework.org/schema/aop 
	   http://www.springframework.org/schema/aop/spring-aop.xsd">
	<bean id="opBean" class="com.w3codebox.Operation">	</bean>
	<bean id="trackMyBean" class="com.w3codebox.TrackOperation"></bean>
	<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>

今、実際のメソッドと呼びましょう。

ファイル: Test.java

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation e = (Operation) context.getBean("opBean");
		System.out.println("calling msg...");
		e.msg();
		System.out.println("calling m...");
		e.m();
		System.out.println("calling k...");
		e.k();
	}
}

出力

msg()を呼び出しています...
追加の関心
msg() メソッドが呼び出されました
calling m...
追加の関心
m() method invoked
calling k...
追加の関心
k() method invoked

msg()、m()、k()メソッドが呼び出される前に他の問題も表示されます。

以下のようにシニクションエクレーション式を変更すると、

@Pointcut("execution(")* Operation.m*(..))")

今、Operationクラスでmで始まるメソッドにさらに注目します。出力は以下のようになります:

msg()を呼び出しています...
追加の関心
msg() メソッドが呼び出されました
calling m...
追加の関心
m() method invoked
calling k...
k() method invoked

k()メソッドが呼び出される前に他の問題が印刷されないことが分かります。


2、@Afterの例

実際のビジネスロジックメソッドが呼び出された後、アフターアドバイスのAspectJが適用されます。これを使用してログ管理、セキュリティ、通知などを行うことができます。

ここでは、以下を仮定しています Operation.java applicationContext.xml および Test.java 文件與@Before示例中給出的文件相同。

ファイル: TrackOperation.Java
package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
	@Pointcut("execution(")* Operation.*(..))")
	public void k(){}//ポイントカット名
	@After("k()")//アドバイスの後のポイントカットを適用しています
	public void myadvice(JoinPoint jp)//アドバイスの後でアドバイス
	{
		System.out.println("additional concern");
		//System.out.println("メソッドシグネチャ: " + "Method Signature: ");  + jp.getSignature());
	}
}
 

出力

msg()を呼び出しています...
msg() メソッドが呼び出されました
追加の関心
calling m...
m() method invoked
追加の関心
calling k...
k() method invoked
追加の関心
 

msg()、m()、k()メソッドが呼び出された後、他の問題も発生します。


3、@AfterReturningの例

アドバイスの後で使用することで、アドバイスで結果を取得できます。

以下の内容を含むクラスのビジネスロジックを作成します。

ファイル: Operation.java

package com.w;3codebox;
public class Operation{
	public int m(){System.out.println("m() メソッドが呼び出されました");return 2;}
	public int k(){System.out.println("k() メソッドが呼び出されました");return 3;}
}
 

アドバイスの後で含まれる側面クラスを作成します。

ファイル: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterReturning(
		      pointcut = "execution(* Operation.*(..))",
		      returning= "result")
		      
	public void myadvice(JoinPoint jp, Object result)//アドバイス(アドバイスを返信後)
	{
		System.out.println("additional concern");
		System.out.println("メソッドシグネチャ: " + "Method Signature: ");  + jp.getSignature());
		System.out.println("結果をアドバイスで表示: ")+result);
		System.out.println("end of after returning advice...");
	}
}
 

ファイル: applicationContext.xml

与@Beforeアドバイス例で提供された

ファイル: Test.java

現在、実際のメソッドを呼び出すTestクラスを作成します。

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation e = (Operation) context.getBean("opBean");
		System.out.println("calling m...");
		System.out.println(e.m());
		System.out.println("calling k...");
		System.out.println(e.k());
	}
}
 

出力

calling m...
m() method invoked
追加の関心
方法簽名:int com.w3codebox.Operation.m()
advice中的結果: 2
end of after returning advice...
2
calling k...
k() method invoked
追加の関心
方法簽名:int com.w3codebox.Operation.k()
advice中的結果: 3
end of after returning advice...
3
 

您可以看到返回值已打印兩次,一次是由TrackOperation類打印,第二次是Test類。


4、@Around示例

圍繞通知的AspectJ在調用實際的业务逻辑方法之前和之后都得到应用。

在此,我們是假設   applicationContext.xml 文件與@Before示例中給出的文件相同。

創建一個包含實際業務邏輯的類。

ファイル: Operation.java

package com.w;3codebox;
public class Operation{
	public void msg(){System.out.println("msg() is invoked");}
	public void display(){System.out.println("display() is invoked");}
}
 

創建包含圍繞建議的方面類。

您需要在advice方法中傳遞   PreceedingJoinPoint 参照、以利我們通過調用proce來執行請求()方法。

ファイル: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation
{
	@Pointcut("execution(")* Operation.*(..))")
	public void abcPointcut(){}
	@Around("abcPointcut()")
	public Object myadvice(ProceedingJoinPoint pjp) throws Throwable 
	{
		System.out.println("実際のメソッド呼び出し前の追加の懸念");
		Object obj = pjp.proceed();
		System.out.println("実際のメソッド呼び出し後の追加の懸念");
		objを返します;
	}
}
 

ファイル: Test.java

現在、実際のメソッドを呼び出すTestクラスを作成します。

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new classPathXmlApplicationContext("applicationContext.xml");
		Operation op = (Operation) context.getBean("opBean");
		op.msg();
		op.display();
	}
}
 

出力

実際のメソッド呼び出し前の追加の懸念
msg()が呼び出されます
実際のメソッド呼び出し後の追加の懸念
実際のメソッド呼び出し前の追加の懸念
display()が呼び出されます
実際のメソッド呼び出し後の追加の懸念
 

msg()とメソッドの表示前に後で、他の問題もプリントアウトされます。


5、@AfterThrowingの例

after throwアドバイスを使用して、TrackOperationクラスで例外をプリントアウトすることができます。AspectJ AfterThrowingアドバイスの例を見てみましょう。

ビジネスロジックを含むクラスを作成します。

ファイル: Operation.java

package com.w;3codebox;
public class Operation{
	public void validate(int age) throws Exception{
	if(age<18){
		throw new ArithmeticException("有効な年齢ではありません");
	}
	else{
		System.out.println("投票に感謝します");
	}
	}
}
 

アドバイスが投げられた後に含まれる方面クラスを作成します。

ここでは、例外を捕まえるためにThrowable参照を渡す必要があります。

ファイル: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterThrowing(
		      pointcut = "execution(* Operation.*(..))",
		      throwing = "error")
		      
	public void myadvice(JoinPoint jp, Throwable error)//it is advice
	{
		System.out.println("additional concern");
		System.out.println("メソッドシグネチャ: " + "Method Signature: ");  + jp.getSignature());
		System.out.println("例外は: " + "Exception is: ");+error);
		System.out.println("advice throwingの後の終了...");
	}
}
 

ファイル: applicationContext.xml

与@Beforeアドバイス例で提供された

ファイル: Test.java

現在、実際のメソッドを呼び出すTestクラスを作成します。

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation op = (Operation) context.getBean("opBean");
		System.out.println("calling validate...");
		try{
			op.validate(19);
		}catch(Exception e){System.out.println(e);}
		System.out.println("calling validate again...");
		try{
		    op.validate(11);
		}catch(Exception e){System.out.println(e);}
	}
}
 

出力

validate を呼び出します...
投票のお礼
validate を再び呼び出します...
追加の関心
メソッドシグネチャ: void com.w3codebox.Operation.validate(int)
例外は: java.lang.ArithmeticException: 无効な年齢
throwing アドバイスの後の終わり...
java.lang.ArithmeticException: 无効な年齢