Spring之AOP模塊

n672 9年前發布 | 24K 次閱讀 Spring JEE框架

AOP(AspectOriented 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{
      //調用對象的方法前執行該方法
      //參數分別為被調用的方法、被調用方法的參數、對象
      publicvoid 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{
      //參數分別為方法返回值、被調用方法、方法參數、被攔截的對象
      publicvoid afterReturning(Object value,Method method,Object [] args,Object instance) throwsThrowable{
                           System.out.println("方法:"+method.getName()+"執行完畢,返回值為:"+value);
      }

}

//異常攔截器捕獲異常
import  org.springframework.aop.ThrowAdvice
public class ThrowsInterceptor implements ThrowAdvice{
      //參數分別為被調用的方法、方法參數、對象實例、拋出的異常
      //前三個參數可以省略,第四個參數是必須的,這樣設計是為了使開發者靈活地定義多個方法捕獲各種不同的異常
      publicvoid afterThrowing(Method method,Object [] args,Object instance,AccountExceptionex) throws Throwable {
             System.out.println("方法:"+method.getName()+"拋出了異常:"+ex);
      }

      publicvoid 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>

 本文由用戶 n672 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!