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)