1. 程式人生 > >Spring之面向切面程式設計(AOP)四種通知

Spring之面向切面程式設計(AOP)四種通知

面向切面程式設計(AOP)

面向切面的程式設計:指很多功能都有重複的程式碼,把這些重複的程式碼獨立出來實現,再在執行的時候動態加入“切面類程式碼”。

AOP是一種設計思想,和具體的程式碼實現無關。

優點:

      A、把共性功能和核心業務功能解耦。

      B、共性程式碼的複用性

      C、動態刪除或增加切面類,不影響原來的程式碼

Aop的實現

前置通知,後置通知,環繞通知、異常通知

用新增日誌檔案為例,描述前置通知,後置通知,環繞通知三種通知,即把核心類和切面類組合的方式

以下均是XML配置方式宣告切面

1、前置通知

(1)、定義介面 IStudent

public interface IStudent{

   public boolean add(String id,String name);

   public boolean update(String id;String name);

   public boolean delete(String id);

}

注:將方法返回值定義為boolean是為了通過booleanValue()方法將值返回給切面類

(2)、實現介面的實體類StudentDao

public class StudentDao implements IStudent{

   public boolean add(String id,String name){

      System.out.println("正在實現 sava 方法");

      System.out.println("新增學生編號:"+id+" 姓名:"+name);

      return true;

   }

public boolean update(String id,String name){

      System.out.println("正在實現 update 方法");

      System.out.println("修改學生編號:"+id+" 姓名:"+name);

      return true;

   }

public boolean delete(String id){

      System.out.println("正在實現 delete 方法");

      System.out.println("刪除學生編號:"+id);

      return true;

   }

}

(3)、定義切面類BeforeAdvice   需要實現MethodBeforeAdvice介面

public class BeforeAdvice implements MethodBeforeAdvice{

   public void befor(Method targetMethod,Object[] methodArgs,Object targetClass){

      String className=targetClass.getClass().getName();//類名

      String methodName=targetMethod.getName();//方法名

      //獲取具體的操作時間並記錄

      Date date=new Date();

      String currentTime=DateFormat.getDateInstance().format(date);   //獲取當前時間並轉化成字串

      String messge="【"+currentTime+“】”+className+"."+methodName+"方法被執行";

      System.out.println(message);

   }

}

注:befor()方法中的引數Method targetMethod表執行的是核心程式碼的哪個方法,Object[] methodArgs表核心程式碼中的所有方法,Object targetClass表要找的目標類

(4)、建立配置檔案applicationContext.xml

<?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.xsd">

   <bean id="stuPoint" class="com.bean.StudentDao"/><!--核心業務類-->

   <bean id="beforeLogin" class="com.bean.BeforeAdvice"/><!--切面類-->

   <!--匯入包中自帶的類  是一個代理工廠類    用來組合核心類和切面類-->

   <bean id="studentfactory" class="org.springframework.aop.framewoke.proxyFactoryBean">

      <property name="proxyInterfaces">   <!--核心業務介面-->

         <value>com.bean.Istudent</value>  

      </property>

      <property name="interceptorNames">   <!--切面類-->

          <value>beforeLogin</value>  

      </property>

      <property name="target" ref="stuPoint"/>   <!--核心類-->

   </bean>

</beans>

注:配置檔名最好不變applicationContext.xml,否則需在web.xml中配置

(5)、建立StudentServlet

......

protected void doPost(HttpServletRequest request, HttpServletResponse response) {

    ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(this.getServletContext);

   IStudent stu=(IStudent)ac.getBean("studentfactory");   //代理工廠類的id

   stu.add("111","張三");

   stu.update("111","李思");

   stu.delete("111");

}

(6)、配置web.xml

<listener>

   <listener-calss>

      org.springframework.web.context.ContextLoaderListener

   </listener-class>

</listener>

<servlet>
      <servlet-name>StudentServlet</servlet-name>
      <servlet-class>com.bean.StudentServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>StudentServlet</servlet-name>
      <url-pattern>/aop</url-pattern>

  </servlet-mapping>

(7)、將web專案釋出到伺服器上,在位址列中輸入aop,驗證結果

2、後置通知

步驟1、2、5、6、7同上

(3)、修改切面類AfterAdvice,需要實現AfterRetruningAdvice介面

public void afterReturning(Object returnValue,Method targetMehod,Object[] methodArgs,Object targetClass){

   boolean success=((Boolean)returnValue).booleanValue();

   if(success){ 

       String methodName=targetMethod.getName();

       String className=targetClass.getClass().getName();

       Date date=new Date();

       String currentTime=DateFormat.getDateInstance().format(date);

       String str="【"+currentTime+"】"+className+"."+methodName+"方法被執行";

   }  

}

注:Object returnValue表核心業務程式碼某個方法的返回值

(4)、在applicationContext.xml配置檔案中,只需修改切面類即可

3、環繞通知

步驟1、2、5、6、7同上

(3)、切面類ArroundAdvice,需實現MethodInterceptor介面

public class ArroundAdvice implemets MethodInterceptor{

   public Object invoke (MethodInvocation invocation){

      System.out.println("開始執行"+invocation.getMethod().getName+"方法");

      Object obj=invocation.proceed();

      System.out.println("結束執行"+invocation.getMethod().getName+"方法");

      return obj;

   }

}

(4)、相同方式修改配置檔案

4、異常通知

需實現org.springframework.aop.ThrowsAdvice介面,不需實現其中方法

public class ThrowTest implemets ThrowsAdvice{

   public void afterThrow([method],[args],[target],subclassofThrowable){

       //異常處理程式碼

   }

}

注:subclassofThrowable表Throwable的自類,即子類異常

總結:

前置通知:實現MethodBeforeAdvice介面,方法public void before(Method targetMethod, Object[] methodArgs, Object targetClass){}

後置通知:實現AfterReturningAdvice介面,方法public void afterReturning(Object returnValue, Method targetMethod, Object[] methodArgs,Object targetClass)  {}

環繞通知:實現 MethodInterceptor介面,方法public Object invoke(MethodInvocation invocation) {}
異常通知:實現ThrowsAdvice介面,自定義方法public void afterThrowing([Method],[args],[target],subclassOfThrowable)