AOP三種代理模式:靜態(tài)代理、jdk、CGLIB

代理模式是常用的 Java 設計模式,代理類可以分為兩種:
*靜態(tài)代理:由程序員或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的 .class字節(jié)碼 文件就已經(jīng)存在。
*動態(tài)代理:在程序運行時,工具類會動態(tài)的生成代理類的 .class字節(jié)碼 緩存在內存中,再運用反射機制,實例化出代理對象。動態(tài)代理有以下幾種實現(xiàn)形式:JDK自帶的動態(tài)代理(常用)、CGLIB(常用)、javaassist字節(jié)碼操作庫實現(xiàn)、ASM(底層使用指令,可維護性較差)。

靜態(tài)代理

兩種實現(xiàn)方式:
*基于接口的靜態(tài)代理:只能針對有接口的類進行代理。
*基于繼承的靜態(tài)代理:無法對 static、final 類或方法進行代理。

基于接口的靜態(tài)代理

public interface Person {
    void doSomeThing();
}

public class ChinesePerson implements Person {

    @Override
    public void doSomeThing() {
        System.out.println("ChinesePerson do some thing");
    }
}

public class InterfaceStaticProxy implements Person {

    private Person person;

    InterfaceStaticProxy(Person person){
        this.person = person;
    }

    @Override
    public void doSomeThing() {
        System.out.println("before interface static proxy");
        try{
            person.doSomeThing();
        }catch (Exception ex){
            System.out.println("ex: " + ex.getMessage());
            throw ex;
        } finally {
            System.out.println("after interface static proxy");
        }
    }
}

public class Client {
    public static void main(String ar[]){
        Person proxy = new InterfaceStaticProxy(new ChinesePerson());
        proxy.doSomeThing();
    }
}

//執(zhí)行結果
before interface static proxy
ChinesePerson do some thing
after interface static proxy

基于繼承的靜態(tài)代理

public class ChinesePerson {
    public void doSomeThing() {
        System.out.println("ChinesePerson do some thing");
    }
}

public class InheritStaticProxy extends ChinesePerson {

    @Override
    public void doSomeThing() {
        System.out.println("before inherit static proxy");
        super.doSomeThing();
        System.out.println("after inherit static proxy");
    }
}

public class Client {
    public static void main(String ar[]){
        ChinesePerson person = new InheritStaticProxy();
        person.doSomeThing();
    }
}

//執(zhí)行結果
before inherit static proxy
ChinesePerson do some thing
after inherit static proxy

動態(tài)代理

程序運行中,工具類會動態(tài)的生成代理類的 .class字節(jié)碼 緩存在內存中,再運用反射機制,實例化出代理對象。實現(xiàn)方式是 jdk代理 和 cglib。

JDK代理

1.定義一個類 JdkProxy 實現(xiàn)接口 InvocationHandler。
2.在類 JdkProxy 的構造函數(shù)的入?yún)⒅校瑐魅腩?ChinesePerson 的實例 chinesePerson。
3.在類 JdkProxy 的方法 invoke() 中使用 method.invoke(this.chinesePerson, args); 調用真實對象 chinesePerson 的方法,并在方法的 執(zhí)行前、執(zhí)行后、異常時 輸出日志。

public interface Person {
    void doSomeThing();
}

public class ChinesePerson implements Person {

    @Override
    public void doSomeThing() {
        System.out.println("ChinesePerson do some thing");
    }
}

public class JdkProxy implements InvocationHandler {

    private ChinesePerson chinesePerson;

    JdkProxy(ChinesePerson chinesePerson){
        this.chinesePerson = chinesePerson;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before jdk dynamic proxy");
        Object result;
        try{
            result = method.invoke(this.chinesePerson,args);
        }catch (Exception ex){
            System.out.println("ex: " + ex.getMessage());
            throw ex;
        } finally {
            System.out.println("after jdk dynamic proxy");
        }
        return result;
    }
}

public class Client {
    public static void main(String ar[]){
        //創(chuàng)建動態(tài)代理類的實例
        Person proxy = (Person) Proxy.newProxyInstance(Client.class.getClassLoader(),new Class[]{Person.class},new JdkProxy(new ChinesePerson()));
        proxy.doSomeThing();
    }
}

//執(zhí)行結果
before jdk dynamic proxy
ChinesePerson do some thing
after jdk dynamic proxy

CGLIB代理

1.定義一個類 CglibProxy 實現(xiàn)接口 MethodInterceptor。
2.在類 CglibProxy 的方法 intercept() 中使用 methodProxy.invokeSuper(o, objects); 調用父類 RealSubject 的方法,并在方法的 執(zhí)行前、執(zhí)行后、異常時 輸出日志。

public class ChinesePerson {
    public void doSomeThing() {
        System.out.println("ChinesePerson do some thing");
    }
}

public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before cglib dynamic proxy");
        Object result;
        try {
            result = methodProxy.invokeSuper(o, objects);
        } catch (Exception ex) {
            System.out.println("ex: " + ex.getMessage());
            throw ex;
        } finally {
            System.out.println("after cglib dynamic proxy");
        }
        return result;
    }
}

public class Client {
    public static void main(String ar[]){
        //創(chuàng)建一個類生成器 enhancer,設置其父類為 ChinesePerson.class,設置其回調函數(shù)為 new CglibProxy()。
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(ChinesePerson.class);
        enhancer.setCallback(new CglibProxy());

        // 創(chuàng)建動態(tài)代理類的實例 proxy,執(zhí)行方法 doSomething() 。
        ChinesePerson proxy = (ChinesePerson) enhancer.create();
        proxy.doSomeThing();
    }
}

//執(zhí)行結果
before cglib dynamic proxy
ChinesePerson do some thing
after cglib dynamic proxy
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容