其實AOP的思想如今講的已經不少了,自己沒有什麼難點,難的是AOP有本身的一套術語,而咱們常常被這套術語搞暈。術語沒招,只能理解背誦了,儘管背誦很討厭,可你們都這麼說,不知道,就會被說暈。html
AOP思想:以下圖,面向切面編程。就是「切「。執行本身的方法時,「在以前,以後,異常,返回,或者先後」都去順便執行一下其餘業務方法,切面就是其餘業務方法。java
AOP術語:以下圖,簡單示例編程
通知:通知定義了切面是什麼以及什麼時候使用,首先該通知方法實現了「作什麼的代碼業務邏輯」,而後肯定了在何時執行。ide
前置通知:在目標方法調用以前調用通知。測試
後置通知:在目標方法完成以後調用通知。this
返回通知:在目標方法成功執行以後調用通知。spa
異常通知:在目標方法拋出異常後調用通知。代理
環繞通知:通知包裹了被通知的方法,在被通知的方法調用以前和以後執行的自定義行爲。htm
鏈接點:鏈接點 是在應用執行過程當中可以插入 切面 的一個點。這個點能夠是調用方法時、拋出異常時、甚至修改一個字段時。切面代碼能夠利用這些點插入到應用的正常流程之中,並添加新的行爲。對象
切點:切點就是在 「哪一個鏈接點或哪些鏈接點處」執行通知。定義了何處執行。
切面:通知+切點=切面 定義了 1.什麼時候2.何處3.幹什麼 這三要素。
如下的兩個概念定義瞭如何實現AOP
引入:引入容許咱們向現有的類添加新方法或屬性。而無需修改這些現有的類的狀況下,讓他們具備新的行爲和狀態。
織入:是切面應用到目標對象並建立新的代理對象的過程。
這兩個概念都是 「動做」。
在目標對象的生命週期裏能夠有多個點進行織入(這裏要了解一下 java類的運行過程)
編譯期:切面在目標類編譯時被織入,這種方式須要特殊的編譯器。
類加載期:切面在目標類加載到JVM時被織入。這種方式須要特殊的類加載器(ClassLoader),它能夠在目標類被引入應用以前加強該目標類的字節碼。
運行期:切面在應用運行的某個時刻被織入。(通常狀況下,在織入切面時,AOP容器會爲目標對象動態的建立一個代理對象)
AOP實現:
JAVA靜態代理 : 代理對象和被代理對象實現相同的接口。
//接口
public interface StaticProxy {
void action();
}
//被代理類
public class BProxy implements StaticProxy {
@Override
public void action() {
System.out.println(BProxy.class.getName()+":作一些事情");
}
}
//代理類
public class DProxy implements StaticProxy{
StaticProxy BProxy;
public DProxy() {
BProxy = new BProxy();
}
@Override
public void action() {
System.out.println(DProxy.class.getName()+":先作一些事情");
BProxy.action();
System.out.println(DProxy.class.getName()+":再作一些事情");
}
}
JDK動態代理:動態代理類的字節碼在程序運行時由Java反射機制動態生成。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力。一個類 和一個接口實現。JDK動態代理的缺點:被代理類必須是實現接口的類。
//代理類 實現 InvocationHandler
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//目標方法以前執行
System.out.println("do sth Before...");
//經過反射機制來調用目標類方法
Object result = method.invoke(target, args);
//目標方法以後執行
System.out.println("do sth After...\n");
return result;
}
}
//供被代理類實現的接口
public interface userSrevices {
public void addUser();
public void deleteUser();
}
//實現接口的被代理類
public class userSrevicesImpl implements userSrevices{
@Override
public void addUser() {
System.out.println("增長了一個用戶");
}
@Override
public void deleteUser() {
System.out.println("刪除了一個用戶");
}
}
//測試
public class test {
public static void main(String[] args) {
//被代理類
userSrevices target = new userSrevicesImpl();
//代理類
DynamicProxy handle = new DynamicProxy(target);
//獲取代理
userSrevices proxy = (userSrevices)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handle);//Proxy類建立代理對象。
//執行
proxy.addUser();
proxy.deleteUser();
}
}
Cglib動態代理:(目前還沒有有實例。。。故引用一哈別的大神的講解)http://www.javashuo.com/article/p-brwlvetb-gd.html
AspectJ實現:
未完待續。