首先声明,本为并非原创,大量参考自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");
    }
}