AOP(Aspect Oriented Programming,面向切面編程)是Spring框架的一個重要特征。
Spring推薦使用接口編程。
Spring提供三種攔截器:方法前攔截器、返回後攔截器、異常拋出攔截器。
攔截器定義
//Service接口
public interface IAopService{
public void withAop() throws Exception; //將會被攔截
public void withoutAop() throws Exception; //不會被攔截
}
public class AopServiceImpl implements IAopService{
private String name;
public void withAop() throws Exception{
System.out.println("有AOP的函數運行。name:"+name);
if(name.trim().length() == 0){
throw new AccountException("name屬性不能為空");
}
}
public void withoutAop() throws Exception{
System.out.println("沒有AOP的函數運行。");
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
//方法前攔截器,檢查name是否為空
import org.springframework.aop.MethodBeforeAdvice;
public class MethodBeforeInterceptor implements MethodBeforeAdvice{
//調用對象的方法前執行該方法
//參數分別為被調用的方法、被調用方法的參數、對象
public void before(Method method,Object [] args,Object instance) throws Throwable{
System.out.println("即將執行方法:"+method.getName());
//
if(instance instanceof AopServiceImpl){
String name = ((AopServiceImpl)instance).getName();
if(name == null){
throw new NullPointerException("name不能為空");
}
}
}
}
//返回後攔截器
import org.springframework.aop.AfterReturningAdvice;
public class MethodAfterInteceptor implements AfterReturningAdvice{
//參數分別為方法返回值、被調用方法、方法參數、被攔截的對象
public void afterReturning(Object value,Method method,Object [] args,Object instance) throws Throwable{
System.out.println("方法:"+method.getName()+"執行完畢,返回值為:"+value);
}
}
//異常攔截器捕獲異常
import org.springframework.aop.ThrowAdvice;
public class ThrowsInterceptor implements ThrowAdvice{
//參數分別為被調用的方法、方法參數、對象實例、拋出的異常
//前三個參數可以省略,第四個參數是必須的,這樣設計是為了使開發者靈活地定義多個方法捕獲各種不同的異常
public void afterThrowing(Method method,Object [] args,Object instance,AccountException ex) throws Throwable {
System.out.println("方法:"+method.getName()+"拋出了異常:"+ex);
}
public void afterThrowing(NullPointerException ex) throws Throwable {
System.out.println("拋出了異常:"+ex);
}
}
攔截器配置
Spring無法將Service的實現類與攔截器直接組裝,因為沒有對應的setter、getter方法。安裝時借助的是Spring的代理類,把攔截器安裝到NameMatchMethodPointcutAdvisor中,把自動以的Service安裝到ProxyFactoryBean中,然後組裝到一塊
<!-- 方法前攔截器MethodBeforeInterceptor安裝到NameMatchMethodPointcutAdvisor中 -->
<bean id="aopMethodBeforeInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">
<!-- 攔截器的實現類-->
<property name="advice">
<bean class="com.clf.spring. MethodBeforeInterceptor">
</property>
<!-- 欲攔截的方法名-->
<property name="mappedName" value="withAop"> </property>
</bean>
<!-- 類似的方式配置返回後前攔截器MethodAfterInteceptor -->
<bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="com.clf.spring. MethodAfterInteceptor">
</property>
<property name="mappedName" value="withAop"> </property>
</bean>
<!-- 類似的方式配置異常前攔截器MethodAfterInteceptor -->
<bean id="aopThrowsInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="com.clf.spring. ThrowsInterceptor">
</property>
<property name="mappedName" value="withoutAop"> </property>
</bean>
<!-- Service實現類,安裝到ProxyFactoryBean -->
<bean id="aopService" class="org.springframework.aop.ProxyFactoryBean">
<!-- 安裝攔截器-->
<property name="interceptorNames">
<list>
<value>aopMethodBeforeInterceptor</value>
<value>aopMethodAfterInterceptor</value>
<value>aopThrowsInterceptor</value>
</list>
</property>
<!—被攔截的對象-->
<property name="target">
<bean class="com.clf.spring.AopServiceImpl">
<property name="name" value="HelloSpring"></property>
</bean>
</property>
</bean>
AOP相關概念
切面Aspect
在本例中,方法withAop()、withoutAop()中都有一些代碼,這些代碼可以看做是AOP中的切面,可以將切面理解為模塊
通知Advisor
本例的三個攔截器都是實現自某個接口,從類名上看就知道三個攔截器都是AOP中的通知。一旦Spring符合條件,就會派發出通知,即一些需要執行的代碼,能實現某種功能
切入點Pointcut
在配置攔截器時,XML中只配置了withAop()方法使用攔截器,而withoutAop()方法沒有配置攔截器,這種配置是借助於org.springframework.aop.support. NameMatchMethodPointcutAdvisor完成的。這就是一個切入點,配置時可以使用通配符。該類明上也帶有Advisor是因為它也是用通知實現的
簡單地說,切入點負責往什麼地方插入代碼,而通知負責插入什麼代碼
Spring提供靈活的切入點配置,例如使用正則表達式
<bean id="advisorTest" class="org.springframework.aop.support.RegexMethodPointcutAdvisor">
<property name="interceptor">
<ref local="someInterceptor">
</property>
<property name="pattern">
<list>
<value>.*get*</value>
<value>.*set*</value>
</list>
</property>
</bean>
--------------------------------------分割線 --------------------------------------
Spring中如何配置Hibernate事務 http://www.linuxidc.com/Linux/2013-12/93681.htm
Struts2整合Spring方法及原理 http://www.linuxidc.com/Linux/2013-12/93692.htm
基於 Spring 設計並實現 RESTful Web Services http://www.linuxidc.com/Linux/2013-10/91974.htm
Spring-3.2.4 + Quartz-2.2.0集成實例 http://www.linuxidc.com/Linux/2013-10/91524.htm
使用 Spring 進行單元測試 http://www.linuxidc.com/Linux/2013-09/89913.htm
運用Spring注解實現Netty服務器端UDP應用程序 http://www.linuxidc.com/Linux/2013-09/89780.htm
Spring 3.x 企業應用開發實戰 PDF完整高清掃描版+源代碼 http://www.linuxidc.com/Linux/2013-10/91357.htm
--------------------------------------分割線 --------------------------------------
Spring 的詳細介紹:請點這裡
Spring 的下載地址:請點這裡