1. 程式人生 > >Java開發雜談(八)代理

Java開發雜談(八)代理

1、代理簡介

代理分為靜態代理和動態代理,靜態代理實現簡單,動態代理功能更加強大。靜態代理是AOP框架會在編譯階段生成AOP代理類,因此稱為編譯時增強。動態代理是執行時增強,AOP框架不會去修改位元組碼,而是在記憶體中臨時為方法生成一個AOP物件,這個AOP物件包含了目標物件的全部方法,並且在特定的切點做了增強處理,並回調原物件的方法。

動態代理有兩種實現,jdk動態代理和cglib代理:

jdk動態代理的原理是實現介面的例項,攔截定於介面中的目標方法,效能更優,是spring生成代理的優先選擇。缺點是隻能代理實現了介面的類,沒有實現介面的類不能實現JDK動態代理。

cglib代理的原理是使用cglib庫中的位元組碼動態生成技術,生成被代理類的子類例項,可以攔截代理類中的任一public方法的呼叫,無論目標方法是否定義與介面中,更通用,但效能相對jdk代理差一些。

2、JDK動態代理實現

// 動態代理類
public class DynamicProxy implements InvocationHandler
{
    // 這個就是我們要代理的真實物件
    private Object subject;
    
    //    構造方法,給我們要代理的真實物件賦初值
    public DynamicProxy(Object subject)
    {
        this.subject = subject;
    }
    
    @Override
    public Object invoke(Object object, Method method, Object[] args)
            throws Throwable
    {
        //  在代理真實物件前我們可以新增一些自己的操作
        System.out.println("before rent house");
        
        System.out.println("Method:" + method);
        
        //    當代理物件呼叫真實物件的方法時,其會自動的跳轉到代理物件關聯的handler物件的invoke方法來進行呼叫
        method.invoke(subject, args);
        
        //  在代理真實物件後我們也可以新增一些自己的操作
        System.out.println("after rent house");
        
        return null;
    }

}
// Client類
public class Client
{
    public static void main(String[] args)
    {
        //    我們要代理的真實物件
        Subject realSubject = new RealSubject();

        //    我們要代理哪個真實物件,就將該物件傳進去,最後是通過該真實物件來呼叫其方法的
        InvocationHandler handler = new DynamicProxy(realSubject);

        /*
         * 通過Proxy的newProxyInstance方法來建立我們的代理物件,我們來看看其三個引數
         * 第一個引數 handler.getClass().getClassLoader() ,我們這裡使用handler這個類的ClassLoader物件來載入我們的代理物件
         * 第二個引數realSubject.getClass().getInterfaces(),我們這裡為代理物件提供的介面是真實物件所實行的介面,表示我要代理的是該真實物件,這樣我就能呼叫這組介面中的方法了
         * 第三個引數handler, 我們這裡將這個代理物件關聯到了上方的 InvocationHandler 這個物件上
         */
        Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
                .getClass().getInterfaces(), handler);
        
        System.out.println(subject.getClass().getName());
        subject.rent();
        subject.hello("world");
    }
}

參考資料:

https://www.cnblogs.com/xiaoluo501395377/p/3383130.html