Spring AOPの例 – Pointcut、Advisor
最後の
Spring AOP adviceの例
では、クラスのメソッド全体が自動的にインターセプトされます。
しかし、ほとんどの場合、ほんの1つか2つの方法を傍受する方法が必要かもしれませんが、これが「Pointcut」の目的です。メソッド名でメソッドをインターセプトできます。さらに、 ‘Pointcut’は ‘Advisor’に関連付ける必要があります。
Spring AOPには、3つの非常に専門的な用語があります –
アドバイス、Pointcut、アドバイザー
、非公式に
実行。
-
Pointcut – メソッド名によってインターセプトするメソッドを指定する
または正規表現パターン。
-
アドバイザ – グループ「アドバイス」と「ポイントカット」を1つのユニットにまとめ、パスする
これをプロキシファクトリオブジェクトに渡します。
最後のリンク://spring/spring-aop-examples-advice/[Spring AOP adviceの例]をもう一度見直してください。
File:CustomerService.java
package com.mkyong.customer.services; public class CustomerService { private String name; private String url; public void setName(String name) { this.name = name; } public void setUrl(String url) { this.url = url; } public void printName(){ System.out.println("Customer name : " + this.name); } public void printURL(){ System.out.println("Customer website : " + this.url); } public void printThrowException(){ throw new IllegalArgumentException(); } }
File:Spring-Customer.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.mkyong.customer.services.CustomerService"> <property name="name" value="Yong Mook Kim"/> <property name="url" value="/"/> </bean> <bean id="hijackAroundMethodBeanAdvice" class="com.mkyong.aop.HijackAroundMethod"/> <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="customerService"/> <property name="interceptorNames"> <list> <value>hijackAroundMethodBeanAdvice</value> </list> </property> </bean> </beans>
File:HijackAroundMethod.java
package com.mkyong.aop; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class HijackAroundMethod implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("Method name : " + methodInvocation.getMethod().getName()); System.out.println("Method arguments : " + Arrays.toString(methodInvocation.getArguments())); System.out.println("HijackAroundMethod : Before method hijacked!"); try { Object result = methodInvocation.proceed(); System.out.println("HijackAroundMethod : Before after hijacked!"); return result; } catch (IllegalArgumentException e) { System.out.println("HijackAroundMethod : Throw exception hijacked!"); throw e; } } }
それを実行します
package com.mkyong.common; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mkyong.customer.services.CustomerService; public class App { public static void main(String[]args) { ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[]{ "Spring-Customer.xml" }); CustomerService cust = (CustomerService) appContext .getBean("customerServiceProxy"); System.out.println("** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** "); cust.printName(); System.out.println("** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** "); cust.printURL(); System.out.println("** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** "); try { cust.printThrowException(); } catch (Exception e) { } } }
出力
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** メソッド名:printNameメソッドの引数:[]HijackAroundMethod:メソッドがハイジャックされる前に! 顧客名:Yong Mook Kim Hijack周辺方法:ハイジャックされた後! ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** Method name : printURL Method arguments :[]HijackAroundMethod : Before method hijacked! Customer website :/HijackAroundMethod : Before after hijacked! ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** メソッド名:printThrowExceptionメソッド引数:[]HijackAroundMethod:メソッドがハイジャックされる前に! HijackAroundMethod:例外をハイジャックしました!
The entire methods of customer service class are intercepted. Later, we
show you how to use “
pointcuts
” to intercept only
printName()
method.
Pointcuts example
You can match the method via following two ways :
-
Name match
-
Regular repression match
1. Pointcuts – Name match example
Intercept a printName() method via ‘pointcut’ and ‘advisor’. Create a
NameMatchMethodPointcut
pointcut bean, and put the method name you
want to intercept in the ‘
mappedName
‘ property value.
<bean id = "customerPointcut" class = "org.springframework.aop.support.NameMatchMethodPointcut"> <property name = "mappedName" value = "printName"/> </bean>
-
DefaultPointcutAdvisor ** advisor beanを作成し、両方を関連付ける
アドバイスとポイントカット。
<bean id = "customerAdvisor" class = "org.springframework.aop.support.DefaultPointcutAdvisor"> <property name = "pointcut" ref = "customerPointcut"/> <property name = "advice" ref = "hijackAroundMethodBeanAdvice"/> </bean>
プロキシの ‘interceptorNames’を ‘customerAdvisor’に置き換えてください(これは
‘hijackAroundMethodBeanAdvice’)。
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService"/> <property name = "interceptorNames"> <list> <value> customerAdvisor </value> </list> </property> </bean>
完全なBean構成ファイル
<beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www .springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd "> <bean id = "customerService" class = "com.mkyong.customer.services.CustomerService"> <property name = "name" value = "Yong Mook Kim"/> <property name = "url" value = "/"/> </bean> <bean id = "hijackAroundMethodBeanAdvice" class = "com.mkyong.aop.HijackAroundMethod"/> <bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService"/> <property name = "interceptorNames"> <list> <value> customerAdvisor </value> </list> </property> </bean> <bean id = "customerPointcut" class = "org.springframework.aop.support.NameMatchMethodPointcut"> <property name = "mappedName" value = "printName"/> </bean> <bean id = "customerAdvisor" class = "org.springframework.aop.support.DefaultPointcutAdvisor"> <property name = "pointcut" ref = "customerPointcut"/> <property name = "advice" ref = "hijackAroundMethodBeanAdvice"/>/bean> </beans>
再度実行し、出力する
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** Method name : printName Method arguments :[]HijackAroundMethod : Before method hijacked! Customer name : Yong Mook Kim HijackAroundMethod : Before after hijacked! ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 顧客のウェブサイト:/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
これで、printName()メソッドだけがインターセプトされます。
-
PointcutAdvisor
Springには
PointcutAdvisor
クラスが付属していますので、アドバイザーやポイントカットを宣言するために
Beanを使用すると、
NameMatchMethodPointcutAdvisor
を使用して単一のBeanに結合できます。
<bean id="customerAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name="mappedName" value="printName"/> <property name="advice" ref="hijackAroundMethodBeanAdvice"/> </bean>
2. Pointcut – 正規表現の例
また、正規表現のpointcut –
RegexpMethodPointcutAdvisor
を使用してメソッドの名前を照合することもできます。
<bean id="customerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="patterns"> <list> <value>.** URL.** </value> </list> </property> <property name="advice" ref="hijackAroundMethodBeanAdvice"/> </bean>
今度は、メソッド名の中に単語「URL」を持つメソッドをインターセプトします。実際には、このクラスを使用してDAOレイヤーを管理することができます。ここでは、
。
DAO。
を宣言して、すべてのDAOクラスをインターセプトしてトランザクションをサポートします。