(Aspect-Oriented Programming, 面向切面編程),是一種新的方法論, 是對傳統 OOP(Object-Oriented Programming, 面向對象編程) 的補充.java
AOP 的主要編程對象是切面(aspect), 而切面模塊化橫切關注點.web
在應用 AOP 編程時, 仍然須要定義公共功能, 但能夠明確的定義這個功能在哪裏, 以什麼方式應用, 而且沒必要修改受影響的類. 這樣一來橫切關注點就被模塊化到特殊的對象(切面)裏.spring
這裏要說明下,因爲Spring AOP是使用JDK動態代理和CGLIB代理實現的,所以Spring AOP只能夠對方法的執行進行攔截,若是須要攔截字段的訪問或更新,則須要像AspectJ這樣的AOP語言。數據庫
另外Spring能夠無縫的集成IOC,Spring AOP 以及AspectJ AOP。編程
將多處地方具備相似功能的代碼(橫切關注點)抽取出來,進行模塊化爲一個方法(通知-Advice);bash
將同一事務的不一樣方法(如前置通知、後置通知)放在一個類中(即,切面–Aspect);markdown
在方法上利用Aspect表達式定義切點,當有匹配其表達式的目標對象方法執行時,會自動爲其創建代理對象-Proxy;模塊化
切面(Aspect): 橫切關注點(跨越應用程序多個模塊的功能)被模塊化的特殊對象--類級別 通知(Advice): 切面必需要完成的工做--即方法(方法級別) 目標(Target): 被通知的對象 代理(Proxy): 向目標對象應用通知以後建立的對象
鏈接點(Joinpoint):post
程序執行的某個特定位置。flex
如類某個方法調用前、調用後、方法拋出異常後等。
鏈接點由兩個信息肯定:
方法(表示程序執行點,即-在哪一個目標方法);
相對點(表示方位,即-目標方法的什麼位置,如調用前、後。。。)
例如 :ArithmethicCalculator#add()方法執行前的鏈接點:
方法爲ArithmethicCalculator#add(); 相對點爲該方法執行前的位置
切入點(pointcut):
AOP 經過切點定位到特定的鏈接點。
經過某種定義來決定哪些方法將會被通知(即須要事物處理),咱們將這個定義秤爲切入點(Pointcut),而每個被處理的方法咱們稱之爲鏈接點(Join Point)。
每一個類都擁有多個鏈接點。例如 ArithmethicCalculator 的全部方法實際上都是鏈接點,即鏈接點是程序類中客觀存在的事務。
類比:鏈接點至關於數據庫中的記錄,切點至關於查詢條件。
切點和鏈接點不是一對一的關係,一個切點經常匹配多個鏈接點.
切點經過 org.springframework.aop.Pointcut 接口進行描述,它使用類和方法做爲鏈接點的查詢條件。
package com.web.aop.impl; import java.util.Arrays; import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /* @Component表示將其放入IOC容器中,使其能夠被自動掃描; @Aspect表示其爲一個切面 */ @Aspect @Component public class LoggingAspect { @Before("execution(int com.web.aop.impl.ArithmeticCalculatorImpl.*(int , int ))") public void beforMethod(JoinPoint joinPoint){ /*獲取方法名*/ String methodName = joinPoint.getSignature().getName(); /*獲取方法的參數*/ List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method"+methodName+" begins with"+args); } /* * 後置通知:在目標方法執行後執行,不管是否拋出異常; * 後置通知中不能訪問目標方法執行後返回的結果; * */ @After("execution(* com.web.aop.impl.*.*(int , int ))") /*表示該包下全部返回類型的全部類的全部方法*/ public void afterMethod(JoinPoint joinPoint){ /*獲取方法名*/ String methodName = joinPoint.getSignature().getName(); System.out.println("The method"+methodName+" ends "); } }