1、AOP 簡介
AOP(Aspect Oriented Programming),即面向切面編程,能夠說是OOP(Object Oriented Programming,面向對象編程)的補充和完善。
OOP引入封裝、繼承、多態等概念來創建一種對象層次結構,用於模擬公共行爲的一個集合。不過OOP只容許開發者定義縱向的關係,
但並不適合定義橫向的關係,例如日誌,事務,安全等。這些功能都是橫向應用在業務處理中,而與它們對應的方法與其餘代碼基本沒有聯繫,
如異常處理和透明的持續性也都是如此,不只增長了大量的代碼量,還爲程序後期的維護增生不少困難。
AOP技術偏偏相反,它利用一種稱爲"橫切"的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,
並將其命名爲"Aspect",即切面。所謂"切面",簡單說就是那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,
下降模塊之間的耦合度,並有利於將來的可操做性和可維護性。
使用"橫切"技術,AOP把軟件系統分爲兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。
橫切關注點的一個特色是,他們常常發生在覈心關注點的多處,而各處基本類似,好比權限認證、日誌、事物。AOP的做用在於分離系統中的各類關注點,
將核心關注點和橫切關注點分離開來。
2、AOP 基本瞭解和通知方法
一、切面(Aspect):一個關注點的模塊化,這個關注點可能會橫切多個對象。事務管理是J2EE應用中一個關於橫切關注點的很好的例子。
在spring AOP中,切面可使用基於模式)或者基於Aspect註解方式來實現。通俗點說就是咱們加入的切面類(好比log類),能夠這麼理解。
二、鏈接點(Joinpoint):在程序執行過程當中某個特定的點,好比某方法調用的時候或者處理異常的時候。在Spring AOP中,
一個鏈接點老是表示一個方法的執行。通俗的說就是加入切點的那個點
三、通知(Advice):在切面的某個特定的鏈接點上執行的動做。其中包括了「around」、「before」和「after」等不一樣類型的通知(通知的類型將在後面部分進行討論)。許多AOP框架(包括Spring)都是以攔截器作通知模型,並維護一個以鏈接點爲中心的攔截器鏈。
四、切入點(Pointcut):匹配鏈接點的斷言。通知和一個切入點表達式關聯,並在知足這個切入點的鏈接點上運行(例如,當執行某個特定名稱的方法時)。
切入點表達式如何和鏈接點匹配是AOP的核心:Spring缺省使用AspectJ切入點語法。
五、引入(Introduction):用來給一個類型聲明額外的方法或屬性(也被稱爲鏈接類型聲明(inter-type declaration))。
Spring容許引入新的接口(以及一個對應的實現)到任何被代理的對象。例如,你可使用引入來使一個bean實現IsModified接口,以便簡化緩存機制。
六、目標對象(Target Object): 被一個或者多個切面所通知的對象。也被稱作被通知(advised)對象。 既然Spring AOP是經過運行時代理實現的,
這個對象永遠是一個被代理(proxied)對象。
七、AOP代理(AOP Proxy):AOP框架建立的對象,用來實現切面契約(例如通知方法執行等等)。在Spring中,AOP代理能夠是JDK動態代理或者CGLIB代理。
八、織入(Weaving):把切面鏈接到其它的應用程序類型或者對象上,並建立一個被通知的對象。這些能夠在編譯時(例如使用AspectJ編譯器),
類加載時和運行時完成。Spring和其餘純Java AOP框架同樣,在運行時完成織入。
通知方法:
1.前置通知(Before advice):在某鏈接點以前執行的通知,但這個通知不能阻止鏈接點以前的執行流程(除非它拋出一個異常)。
2.後置通知(After returning advice):在某鏈接點正常完成後執行的通知:例如,一個方法沒有拋出任何異常,正常返回。
3.異常通知(After throwing advice):在方法拋出異常退出時執行的通知。
4.最終通知(After (finally) advice):當某鏈接點退出的時候執行的通知(不管是正常返回仍是異常退出)。
5.環繞通知(Around Advice):包圍一個鏈接點的通知,如方法調用。這是最強大的一種通知類型。環繞通知能夠在方法調用先後完成自定義的行爲。
它也會選擇是否繼續執行鏈接點或直接返回它本身的返回值或拋出異常來結束執行。
3、Spring對AOP的支持
Spring中AOP代理由Spring的IOC容器負責生成,管理,它的依賴關係也有IOC容器負責。所以,AOP代理能夠直接使用容器中的其餘bean示例做爲目標,
這種關係可由IOC容器的依賴注入提供(不熟悉依賴注入的能夠看看我以前的博文)。Spring建立代理規則爲:
一、默認使用JDK動態代理來建立AOP代理,這樣能夠爲任何接口示例建立代理
二、當須要代理的類不是代理接口時,Spring會切換爲使用CGLIB代理,也可強制使用CGLIB代理。(強制方法:在XML配置中修改 AOP 屬性
spring.aop.proxy-target-class=true或在註釋中修改@EnableAspectJAutoProxy(proxyTargetClass = true)
進行AOP編程的關鍵就是定義切入點和定義加強處理,一旦定義了合適的切入點和加強處理,AOP框架將自動生成AOP代理,
即:代理對象的方法=加強處理+被代理對象的方法
4、Spring AOP 栗子
一、定義一個接口
package com.samter.common;
public interface car {
void run(String name);
}
二、接口的實現類
package com.samter.commonImpl;
public class carImpl implements car{
public void run(String name) {
System.out.println("【一輛】"+name+"正在飆車...");
}
}
三、切面
package com.samter.aspect;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class Aspects {
// 第一個*表明任意返回值類型 後面的表示掃描com.samter下的全部包
// 包下的全部類,類裏面的全部方法,方法的全部參數
@Pointcut("execution(* com.samter.*.*.*(..))")
public void foundCar() {}
@Before(value="foundCar()")
public void foundBefore() {
System.out.println("【交警】發現一輛車正在飆車...");
}
@AfterReturning("foundCar() && args(name,..)")
public void foundAfter(String name) {
System.out.println("【交警】攔下車,車名是「"+name+"」...");
}
@AfterReturning("foundCar()")
public void foundAfter() {
System.out.println("【交警】開罰單");
}
}
四、XML配置
五、測試
package com;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.samter.common.Pig;
import com.samter.common.commo.Dog;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Car car = (Car) context.getBean("car");
car.run(「寶馬」);
}
}
六、結果
【交警】發現一輛車正在飆車...
一輛寶馬正在飆車...
【交警】攔下車,車名是寶馬...
【交警】開罰單
七、後置
1.運行前別忘記導 jar 包(沒有去網上下)
2.運行錯誤時查看是否是類名寫錯了或者是XML文件沒有讀取到,XML放在根路徑下
3.寫測試類是注意不要導錯文件包
八、後記
這裏只寫了前置通知和後置通知,其餘通知除環繞通知外用法都差很少,環繞通知你們能夠去百度下,
網上許多大神都有詳細的栗子。
5、圖片