Spring學習之路(4)——AOP

爲什麼要使用AOP?

AOP是面向對象編程(OOP)的一種補充,目前已成爲一種比較成熟的編程方式。

在傳統的業務處理代碼中,通常都會進行事務處理、日誌記錄等操作。雖然使用OOP可以通過組合或者繼承的方式來達到代碼的重用,但如果要實現某個功能(如日誌記錄),同樣的代碼仍然會分散到各個方法中。這樣,如果想要關閉某個功能,或者對其進行修改,就必須要修改所有的相關方法。這不但增加了開發人員的工作量,而且提高了代碼的出錯率。

爲了解決這一問題,AOP思想隨之產生。AOP採用橫向抽取機制,將分散在各個方法的重複代碼提取出來,然後在程序編譯或運行時,再將這些提取出來的代碼應用到需要執行的地方。這種採用橫向抽取機制的方式,採用傳統的OOP思想顯然是無法辦到的,因爲OOP只能實現父子關係的縱向的重用。雖然AOP是一種新的編程思想,但卻不是OOP的替代品,它只是OOP的延伸和補充。

AOP的使用,使開發人員在編寫業務邏輯時可以專心於核心業務,而不必過多地關注於其他業務邏輯的實現這不但提高了開發效率,而且增強了代碼的可維護性。

 AOP中的名詞概念

Aspect(切面):指橫切性關注點的抽象即爲切面,與類相似,只是兩者的關注點不同,類是對物體特徵的抽象,而切面是對橫切面關注點的抽象。

JoinPoint(連接點):連接點是指那些被攔截到的點,spring中這些點指的是方法。

Pointcut(切入點):切入點是指我們要對那些JoinPoint進行攔截的定義。

Advice(通知):通知是指攔截到JoinPoint之後要做的事情,分爲前置通知、後置通知、異常通知,最終通知、環繞通知。

前置通知和後置通知一個是在連接點之前執行,一個是在連接點退出的時候執行。異常通知是方法拋出異常退出時執行的邏輯。環繞通知是包圍連接點退出的時候執行的邏輯。

AOP註解方式編程的步驟

  1. 定義一個切面類    @Aspect註解
  2. 定義@Pointcut切點,即定義一個方法,指定攔截項目中的那些方法
  3. 定義五中類型中的哪一種通知,即定義了一個方法,表示切點攔截到了方法後,執行什麼功能
  4. beans.xml中添加<aop:aspectj-autoproxy></aop:aspectj-autoproxy>標籤,支持aop的註解
package cn.sdut.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 切面類
 * @author DELL
 *
 */

@Component //組件註解
@Aspect //註解切面類
public class AspectLog {

	//註解切入點作用於cn.sdut.service包下所有的類的方法
	@Pointcut(value="execution(* cn.sdut.service.*.*(..))")
	private void pointCut() {
		
	}
	
	//註解前置通知
	@Before(value="pointCut()")
	public void beforeLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."
	+joinPoint.getSignature().getName()+" is called.. before");
	}
	
	//註解後置通知
	@After(value="pointCut()")
	public void afterLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."
	+joinPoint.getSignature().getName()+" is called.. after");
	}
	
	//返回註解通知
	@AfterReturning(value="pointCut()")
	public void afterReturningLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."+
	joinPoint.getSignature().getName()+" ar is called.. return");
	}
	
	//環繞通知
	@Around(value="pointCut()")
	public Object AroundLog(ProceedingJoinPoint point) throws Throwable {
		System.out.println(point.getSignature().getDeclaringTypeName()+"."+
				point.getSignature().getName()+" ar is called.. start");
		Object object = point.proceed();
		System.out.println(point.getSignature().getDeclaringTypeName()+"."+
				point.getSignature().getName()+" ar is called.. end");
		return object;
	}
	
	//異常通知
	@AfterThrowing(value="pointCut()")
	public void afterThrowingLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."+
	joinPoint.getSignature().getName()+" ar is called.. throwing");
	}
}

AOP的xml方式配置

  • 定義切面類,編寫切面類中的方法
  • beans.xml中配置aop信息

<aop:config>
                <aop:aspect id="myAspect" ref="aspectLog">
                    <aop:pointcut id="mypointcut" expression="execution(* cn.sdut.dao.*.*(..))" />
                    <aop:before method="beforeLog" pointcut-ref="mypointcut"/>
                    <aop:after method="afterLog" pointcut-ref="mypointcut"/>
                    <aop:after-returning method="afterReturningLog" pointcut-ref="mypointcut"/>
                    <aop:around method="aroundLog" pointcut-ref="mypointcut"/>
                    <aop:after-throwing method="afterThrowingLog" pointcut-ref="mypointcut"/>
                </aop:aspect>
            </aop:config>

 

ref指向的是切面類首字母小寫 。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章