java切面編程:概念部分(一)

關於java切面編程瞭解:
      目前java切面編程在java開發及其他軟件開發領域的應用十分廣泛,在java1.5加入註解功能後更是如虎添翼,目前認知值停留在模糊的概念階段:java切面編程通過jdk和cglib兩種動態代理模式,可以在類和方法還有註解上切入,因此其所能實現的功能就十分強悍了。
      切面編程主要優點:在不修改源碼的基礎上更加容易的擴展功能,將功能代碼從業務邏輯中分離出來,便以不至於在業務代碼中需要大量的使用功能代碼和設計模式,如以前的Android SDK開發包。總結起來就是解耦,易擴展,高性能,高效率,高複用率。
      切面編程主要功能:日誌記錄,性能統計,安全控制,事務處理,異常處理,等等。

關於切面編程的概念:
       面向切面編程(Aspect Oriented Programming),以下簡稱AOP。
      通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。(以上概念在百度百科上非常詳細的介紹)

關於AOP的底層實現原理:
      總所周知,AOP的底層由jdk動態代理和cglib動態代理實現,是否還有其他模式,我就不得而知了,但基本上就是這兩個模式,所以首先我們得明白什麼是代理模式(23種基本設計模式中的一種)思想,以及動態代理的實現方式。其概念的東西不在本篇幅中展開詳細的說明,因此要深入瞭解AOP就必須要掌握代理模式和動態代理實現的兩種模式。因此這部分基礎十分重要,必要掌握。

java動態代理的兩種實現方式:
      AOP的攔截功能由java中的動態代理來實現,就是在目標類的基礎上增加切面邏輯,生成增強的目標類。(該切面邏輯可以在目標類函數執行之前,或者目標類執行之後,或者在目標類函數拋出異常的時候執行。不同的切入時機對應不同的Interceptor的種類。如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)

jdk動態代理:
      jdk動態代理是jdk原生就支持的一種代理方式,它的實現原理,就是通過讓target類和代理類實現同一接口,代理類持有target對象,來達到方法攔截的作用,這樣通過接口的方式就有兩個弊端,一是必須保證target類有接口,第二個是如果想要對target類的方法進行攔截,那麼就要保證這些方法在接口中聲明,實現上略微有點限制。
? 示例代碼:略(在ecli-test本地工程中)

1.定義一個簡單的接口

public interface IUser {
void addUser();
}

2.實現該接口

import com.common.service.IUser;
public class UserImpl implements IUser {
public void addUser() {
// 這裏是代碼邏輯,我們省略,只打印一句話,做爲演示
System.out.print("------------add user success----------");
	}
}

3.定義一個代理類實現InvacationHandler

public class MyInvocation implements InvocationHandler {
private Object target;
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 加入該對象執行之前的代碼邏輯,這裏我們只打印一句話,複雜的邏輯也是一樣加在這裏
System.out.print("對象執行之前的代碼邏輯");

// 返回代理對象
Object resultObject = method.invoke(target, args);

// 加入該對象執行之後的代碼邏輯,這裏我們只打印一句話,複雜的邏輯也是一樣加在這裏
System.out.print("對象執行之後的代碼邏輯");
return resultObject;
}
public MyInvocation(Object target) {
this.target = target;
}
}

4.測試調用

public static void main(String[] args) {
// 得到代理對象
MyInvocation myInvocationHandler = new MyInvocation(new UserImpl());
IUser proxy = (IUser) Proxy.newProxyInstance(MyInvocation.class.getClassLoader(),
new Class[] { IUser.class }, myInvocationHandler);
// 調用方法
proxy.addUser();
}

主要實現步驟:新建接口和接口實現類
      代理類實現InvocationHandler接口重寫invoke方法,在該類中傳入target類的接口,通過Proxy.newProxyInstance()方法返回代理對象,在invoke方法中做增強。

cglib動態代理:
       CGLIB(Code Genertation Library)是一個開源項目。意爲強大的高性能代碼生成包,底層通過使用一個小而快的字節碼處理框架ASM,來轉換字節碼並生成新的類,可在運行期擴展java類與實現java接口。
? 示例代碼:略(在ecli-test本地工程中)

1.同樣使用上面的UserImpl類。

2.定義一個代理類實現MethodInerceptor.

public class ProxySaler implements MethodInterceptor {
    public static Object getProxy(Class classs){
        // 通過CGLIB動態代理獲取代理對象的過程
        Enhancer enhancer = new Enhancer();
        // 設置enhancer對象的父類
        enhancer.setSuperclass(classs);
        // 設置enhancer的回調對象
        enhancer.setCallback(new ProxySaler());
        // 創建代理對象
        Object proxy= enhancer.create();
        return proxy;
    }
    /**
     * o:cglib生成的代理對象
     * method:被代理對象方法
     * objects:方法入參
     * methodProxy: 代理方法
     */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("======插入前置通知======");
        Object object = methodProxy.invokeSuper(o, objects);
        System.out.println("======插入後者通知======");
        return object;
    }
}

3.測試調用

public class CGLIBProxy {
    @Test
    public void test(){
        UserImpl proxy = (UserImpl) ProxySaler.getProxy(UserImpl.class);
        proxy.addUser();
    }
}

      主要步驟:代理類實現MethodInteceptor接口,重寫interceptor()方法,並在該方法切入做增強。
      通過Enhancer對象根據target類的字節碼生成相應的代理對象和回調對象
      關於CGLIB的底層實現原理以及其它強大的應用,可以去看源碼。

關於AOP的一些專業術語:(這些概念非常的晦澀,請務必先了解代理模式,以及動態代理)
      Joinpoint(連接點):類裏面可以被增強的方法,這些方法稱爲連接點。
      Pointcut(切入點):所謂切入點是指我們要對哪些Joinpoint(方法)進行攔截的定義。
      Advice(通知/增強):所謂通知就是指攔截到Joinpoint之後我們所有做的事情,通知分爲前置通知,後置通知, 異常通知,最終通知,環繞通知。
      Aspect(切面):是切入點和通知的結合,即對連接點的攔截定義和增強的邏輯或通知。
      Introduction(引介):引介是一種特殊的通知,在不修該類代碼的前提下,Introduction可以在運行期爲類動態地 添加一些方法和屬性。
      Target(目標對象):代理的目標對象(即需要增強的類)
       Weaving(織入):是把增強應用到目標的過程,把advice應用到target的過程。
       Proxy(代理):一個類被AOP織入增強後,就產生一個結果代理類。

概念總結:以上提取了一些重要的面向切面編程的理解的一些前置概念和個人見解,總的來說就是利用代理設計模式實現了動態代理的技術,然後在通過動態代理這些技術來實現面向切面編程,從而解決了一些複雜問題的目的。

spring aop :另起篇幅

springboot aop 註解權限驗證實現:https://segmentfault.com/a/1190000012845239

Aspectj 切面包:另起篇幅

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