Java靜態代理和動態代理

首先聲明,本爲並非原創,大量參考自http://layznet.iteye.com/blog/1182924,一方面做個備份,另一方面也是自己學習的過程。


一、代理

對一個類(委託類,實際完成工作的那個類)方法的調用交給另一個類(代理類,可以靜態或動態生成)來完成。如果委託類和代理類實現了同一個接口,那麼代理就可以很方便的完成。

wKiom1MnrQPDbsxUAACbR0DSCQo263.jpg

二、靜態代理

程序運行前代理類和委託類的關係就已經確定,代理類的字節碼文件已經存在,代理不是運行時生成。

Code list 1, 接口定義:

package proxy.staticy;
public interface Subject {
    void dealTask(String taskName);
}

Code list 2,委託類,真正做事情的類:

package proxy.staticy;
public class RealSubject implements Subject {
    @Override
    public void dealTask(String taskName) {
        System.out.println("正在執行任務: " + taskName);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Code list 3,代理類:

package proxy.staticy;
public class ProxySubject implements Subject {
    private Subject delegate;
    public ProxySubject(Subject delegate) {
        this.delegate = delegate;
    }
    @Override
    public void dealTask(String taskName) {
        long start = System.currentTimeMillis();
        delegate.dealTask(taskName);
        long end = System.currentTimeMillis();
        System.out.println("任務耗時" + (end - start) + "毫秒");
    }
}

Code list 4,生成代理的工廠類:

package proxy.staticy;
public class SubjectStaticFactory {
    public static Subject getInstance() {
        return new ProxySubject(new RealSubject());
    }
}

Code list 5,模擬客戶端:

package proxy.staticy;
public class Client1 {
    public static void main(String[] args) {
        Subject myProxy = SubjectStaticFactory.getInstance();
        myProxy.dealTask("Task one");
    } 
}

三、動態代理

代理類的源碼在運行時有虛擬機反射生成,因此不存在字節碼文件,代理類和委託類的關係在運行時確定。

Code list 6,動態代理對應的調用處理器:(說白了就是類似於代理的類)

/**
 * 動態代理對應的調用處理器
 */
package proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class SubjectInvocationHandler implements InvocationHandler {
                                                                                                                                                                                                                                                                                                                                               
    // 代理類持有一個委託類的對象引用
    private Object delegate;
                                                                                                                                                                                                                                                                                                                                               
    public SubjectInvocationHandler(Object delegate){
        this.delegate = delegate;
    }
                                                                                                                                                                                                                                                                                                                                               
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
                                                                                                                                                                                                                                                                                                                                                   
        // Method的invoke返回Object對象方法執行的結果
        method.invoke(delegate, args);
                                                                                                                                                                                                                                                                                                                                                   
        long end = System.currentTimeMillis();
                                                                                                                                                                                                                                                                                                                                                   
        System.out.println("任務執行耗時"+(end - start)+"毫秒");
                                                                                                                                                                                                                                                                                                                                                   
        return null;
    }
}

Code list 7,生成動態代理對象的工廠類:

/**
 * 生成動態代理對象的工廠.
 */
package proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import proxy.staticy.RealSubject;
import proxy.staticy.Subject;
/**
 * 客戶端調用此方法獲得代理對象,
 * 對客戶端來說,並不知道獲取的是代理對象還是委託對象。
 */
public class DynamicProxyFactory {
    public static Subject getInstance() {
        Subject delegate = new RealSubject();
        InvocationHandler handler = new SubjectInvocationHandler(delegate);
        Subject proxy = (Subject) Proxy.newProxyInstance(
                delegate.getClass().getClassLoader(),
                new Class[] {Subject.class},
                handler);
        return proxy;
    }
}

Code list 8,模擬客戶端:

package proxy.dynamic;
import proxy.staticy.Subject;
public class Client2 {
    public static void main(String[] args) {
        Subject myProxy = DynamicProxyFactory.getInstance();
        myProxy.dealTask("Task two");
    }
}


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