SpringでAOP †
【 用語 】
【 設定ファイルの記述例A 】 <?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.0.xsd"> <!-- 業務ロジックの定義 --> <bean id="testService" class="example.spring.TestServiceImpl" /> <!-- アドバイスの定義 --> <bean id="afterAdvice" class="example.spring.MyAfterAdvice" /> <bean id="beforeAdvice" class="example.spring.MyBeforeAdvice" /> <bean id="aroundAdvice" class="example.spring.MyAroundAdvice" /> <!-- アドバイザの定義 --> <bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" ref="aroundAdvice" /> <!-- 適用するAdviceのbeanidを記述 ※複数NG --> <property name="patterns" value=".*" /> <!-- メソッド名のパターンを記述 ※複数OK(カンマ区切り) --> </bean> <!-- AOPに関する情報を定義 --> <bean id="beanNameAutoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <value>testService</value> <!-- 対象クラスのbeanNameを記述 ※複数OK --> </property> <property name="interceptorNames"> <value>myAdvisor</value> <!-- 対象アドバイザのidを指定 ※複数OK --> </property> </bean> </beans>
【 設定ファイルの記述例B(AspectJスタイル) 】※aspectjweaver.jar が必要。 <?xml version="1.0" encoding="UTF-8"?>
【 各クラスの定義例 】 // 自作のアドバイス(Before) package net.magata; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class MyBeforeAdvice implements MethodBeforeAdvice { // メソッド呼び出し前にログを出力する public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("Beforeアドバイスからのログ出力です"); } } // 自作のアドバイス(After) package net.magata; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class MyAfterAdvice implements AfterReturningAdvice { // メソッド呼び出し後にログを出力する public void afterReturning(Object ret, Method method, Object[] args, Object target) throws Throwable { System.out.println("Afterアドバイスからのログ出力です"); if (target != null){ System.out.println(" 実行クラス:" + target.getClass().getName()); } if (method != null){ System.out.println(" 実行メソッド:" + method.getName()); } if (args != null){ for (int i = 0; i < args.length; i++) { Object arg = args[i]; System.out.println(" 引数" + (i + 1) + ":" + arg.toString()); } } if (ret != null){ System.out.println(" 戻り値:" + ret.getClass().getName()); } } } /* 自作のアドバイス(Around) ※before + After + Throws ( org.aopalliance.intercept.MethodInterceptorなどの invokeメソッドを実装しても可 ) */ package net.magata; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop.MethodBeforeAdvice; import org.springframework.aop.ThrowsAdvice; public class MyAroundAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice { // メソッド呼び出し前にメッセージを出力する public void before(Method method, Object[] args, Object target) throws Throwable { System.out.print("Beforeアドバイスからのログ出力です"); if ((args != null)&&(args.length > 0)) { String argStr = (String)args[0]; System.out.print(" 引数:" + argStr); } System.out.println(""); } // メソッド呼び出し後にメッセージを出力する public void afterReturning(Object ret, Method method, Object[] args, Object target) throws Throwable { System.out.println("Afterアドバイスからのログ出力です"); if (target != null){ System.out.println(" 実行クラス:" + target.getClass().getName()); } if (method != null){ System.out.println(" 実行メソッド:" + method.getName()); } if (args != null){ for (int i = 0; i < args.length; i++) { Object arg = args[i]; System.out.println(" 引数" + (i + 1) + ":" + arg.toString()); } } if (ret != null){ System.out.println(" 戻り値:" + ret.getClass().getName()); } } // 例外発生時にメッセージを出力する public void afterThrowing(Method m, Object[] args, Object target, Throwable ex){ System.out.println("Exception in method: " + m.getName() + " Exception is: "+ex.getMessage()); } } // 業務ロジック package net.magata; public class TestServiceImpl implements TestService { public void methodA(){ System.out.println("methodAを実行(引数なし、戻り値なし)"); } public void methodB(String arg){ System.out.println("methodBを実行(引数:" + arg + "、戻り値なし)"); } public String methodC(String arg){ String ret = "こんにちわ"; System.out.println("methodCを実行(引数:" + arg + "、戻り値:" + ret +")"); return ret; } } // 実行クラス package net.magata; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestMain { public static void main(String[] args) { // アプリケーションコンテキストの取得 ApplicationContext context = new ClassPathXmlApplicationContext("net/magata/applicationContext.xml"); // 業務ロジッククラスのインスタンスを取得 TestService logic = (TestService)context.getBean("testService"); // 業務ロジックA(引数なし)の実行 logic.methodA(); // 業務ロジックB(引数あり)の実行 logic.methodB("Test!!"); // 業務ロジックC(引数あり、戻り値あり)の実行 String res = logic.methodC("Test!!"); } } 【 実行結果(Around適用時) 】 Beforeアドバイスからのログ出力です methodAを実行(引数なし、戻り値なし) Afterアドバイスからのログ出力です 実行クラス:example.spring.TestServiceImpl 実行メソッド: methodA Beforeアドバイスからのログ出力です 引数:Test!! methodBを実行(引数:Test!!、戻り値なし) Afterアドバイスからのログ出力です 実行クラス:example.spring.TestServiceImpl 実行メソッド: methodB 引数1:Test!! Beforeアドバイスからのログ出力です 引数:Test!! methodCを実行(引数:Test!!、戻り値:こんにちわ) Afterアドバイスからのログ出力です 実行クラス:example.spring.TestServiceImpl 実行メソッド: methodC 引数1:Test!! 戻り値:java.lang.String |