如果想對一個bean中的特定方法進行切面編程,而不是所有的方法,就需要設置pointcut了,pointcut允許攔截一個方法通過 方法名 ,一個 pointcut必須和一個advisor想關聯。
一般有以下配置組成:
1:advice 在方法執行前(before)后(after)做出相應的響應。通常是定義一些實現接口的類,然后實現相應的方法,比如:before 對應的實現MethodBeforeAdvice接口 , after對應的實現AfterReturningAdvice , around對應的實現MethodInterceptor接口 , after throwing 對應的實現:ThrowsAdvice 接口, 實現對應的接口的方法即可。
Pointcut 運用的例子:
一:能夠通過以下兩種方式匹配相應的方法:
1:通過name(名稱)匹配。
2:通過正則表達式匹配。
二:通過名稱匹配:
1:通過pointcut 和 advisor 攔截printName方法:創建一個org.springframework.aop.support.NameMatchMethodPointcut的切點bean -----> bookPointcut 即切點(pointcut) 其屬性 mappedName 定義了 需要攔截的方法,就是切點。如下:
- <!-- define a pointcut -->
- <bean id="bookPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
- <property name="mappedName" value="printName" />
- </bean>
2:定義一個advice 相當於 對切點所做的操作, 根據advice的攔截位置需要實現相應的接口,比如: MethodInterceptor 是around對應的接口。
配置片段如下:
- <!-- around method -->
- bean id="aroundMethod" class="com.myapp.core.aop.advice.AroundMethod" />
對應的類:
- package com.myapp.core.aop.advice;
- import java.util.Arrays;
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
- public class AroundMethod implements MethodInterceptor{
- @Override
- public Object invoke(MethodInvocation methodInvocation) throws Throwable {
- // TODO Auto-generated method stub
- System.out.println("method name:" + methodInvocation.getMethod().getName());
- System.out.println("method arguments" + Arrays.toString(methodInvocation.getArguments()));
- System.out.println("Around method : before ");
- try{
- Object result = methodInvocation.proceed();
- System.out.println("Around method : after ");
- return result;
- }catch(IllegalArgumentException e){
- System.out.println("Around method : throw an exception ");
- throw e;
- }
- }
- }
3:定義一個 advisor
advisor 是org.springframework.aop.support.DefaultPointcutAdvisor的bean里面有對應的屬性:
包括:
pointcut 相當於以上定義的:bookPointcut
和
advice相當於以上定義的:aroundMethod
所以advisor對應的配置如下:
- <!-- define a advisor -->
- <bean id="bookAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="pointcut" ref="bookPointcut"/>
- <property name="advice" ref="aroundMethod"></property>
- </bean>
其他部分不變:
完整的配置文件如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <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-3.0.xsd">
- <!-- more bean definitions for data access objects go here -->
- <bean id="book" class="com.myapp.core.aop.advice.Book">
- <property name="name" value="Effective java" />
- <property name="url" value="www.google.cn"/>
- <property name="pages" value="300" />
- </bean>
- <!-- around method -->
- <bean id="aroundMethod" class="com.myapp.core.aop.advice.AroundMethod" />
- <!-- define a pointcut -->
- <bean id="bookPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
- <property name="mappedName" value="printName" />
- </bean>
- <!-- define a advisor -->
- <bean id="bookAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="pointcut" ref="bookPointcut"/>
- <property name="advice" ref="aroundMethod"></property>
- </bean>
- <bean id="bookProxy" class="org.springframework.aop.framework.ProxyFactoryBean" >
- <property name="target" ref="book"/>
- <property name="interceptorNames">
- <list>
- <value>bookAdvisor</value>
- </list>
- </property>
- </bean>
- </beans>
對應的測試類:
- package com.myapp.core.aop.advice;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class MainTest {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("resource/aop.xml");
- Book book = (Book) context.getBean("bookProxy");
- System.out.println("---------------------");
- book.printName();
- System.out.println("---------------------");
- book.printUrl();
- System.out.println("----------------------");
- try{
- book.printThrowException();
- }catch(Exception e){
- // e.printStackTrace();
- }
- }
- }
測試結果:
只有在調用printName方法的時候才應用around的,其他方法不應用around,所以輸出結果如下:
- 三月 20, 2013 5:37:23 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
- INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@eb67e8: startup date [Wed Mar 20 17:37:23 CST 2013]; root of context hierarchy
- 三月 20, 2013 5:37:23 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
- INFO: Loading XML bean definitions from class path resource [resource/aop.xml]
- 三月 20, 2013 5:37:23 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
- INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@157985: defining beans [book,aroundMethod,bookPointcut,bookAdvisor,bookProxy]; root of factory hierarchy
- ---------------------
- method name:printName
- method arguments[]
- Around method : before
- Book name Effective java
- Around method : after
- ---------------------
- Book URL www.google.cn
- ----------------------
只有在printName方法上作用了around,其他方法沒有調用,over。