- 原理
使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
- 静态代理
代理类和目标对象的类都是在编译期间就确定下来了,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样程序开发中必然产生过多的代理。最好可以通过一个代理类完成全部的代理功能。
- 动态代理
客户通过代理类来调用其它对象的方法,是在程序运行时根据需要动态创建目标类的代理对象。
3.1 使用场合:
① 调试
② 远程方法调用
3.2 优势
抽象角色中(接口)声明的多有方法都被转移到调用处理器一个集中的方法中处理,我们就可以更加灵活和统一的处理众多的方法。(即一个代理类搞定)
- 动态代理程序
import java.lang.reflect.*; // 1.接口 interface Human { String getBelief(); void eat(String food); } // 2.被代理类 class SuperMan implements Human { @Override public String getBelief() { return "I believe I can"; } @Override public void eat(String food) { System.out.println("我喜欢吃" + food); } } // 3.生成动态代理类 class ProxyFactory { public static Object getProxyInstance(Object obj) { // 3.1 创建关联类的对象,用于传入Proxy.newProxyInstance方法中的参数3 MyInvocationHandler handler = new MyInvocationHandler(); // 3.2 将被代理类对象传入关联类 handler.bind(obj); // 3.3 动态生成代理类 return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),handler); } } // 4.生成动态代理类与动态的调用被代理方法的关联类 class MyInvocationHandler implements InvocationHandler { private Object o; // 4.1 将被代理类传入 public void bind(Object o) { this.o = o; } @Override // 4.2 实现关联接口中的invoke方法,proxy为动态关联的代理类对象 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 4.3 调用被代理类中的方法,o为被代理类对象 Object returnValue = method.invoke(o, args); return returnValue; } } // 5.测试类 public class ProcyTest { public static void main(String[] args) { // 5.1 创建被代理类的对象 SuperMan superMan = new SuperMan(); // 5.2 动态的生成该对象对应的代理类 Human proxyInstance = (Human)ProxyFactory.getProxyInstance(superMan); // 5.3 代理类调用被代理类的方法 String belief = proxyInstance.getBelief(); System.out.println(belief); proxyInstance.eat("四川火锅"); } } - 动态代理实现过程
- 动态代理各结构关系图
- 调用被代理类方法的Debug调试图
注:proxy参数为关联的动态生成的代理类对象



