代理模式

代理模式:某个代理对象和真实对象都实现同一个接口,代理对象有真实对象的引用,实现的业务还是有真实对象来完成,但是代理对象可以在实现业务加一些别的代码。

静态代理

public interface BuyHouse {

    void buyHouse();
}

定义一个接口

public class BuyHouseImpl implements BuyHouse{

    @Override
    public void buyHouse() {
        System.out.println("买房子");
    }
}
public class BuyHouseProxy implements BuyHouse{

    private BuyHouse buyHouse;

    public BuyHouseProxy(BuyHouse buyHouse){
        this.buyHouse = buyHouse;
    }
    @Override
    public void buyHouse() {
        System.out.println("买房前的准备");
        buyHouse.buyHouse();
        System.out.println("买完后装修");
    }
}

代理类

动态代理

public class DynamicBuyHouse implements InvocationHandler{

    private  BuyHouse buyHouse;

    public DynamicBuyHouse(BuyHouse buyHouse){
        this.buyHouse = buyHouse;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("买房前准备");
        method.invoke(buyHouse,args);
        System.out.println("买房后装修");
        return null;
    }
}
public class Test {
    public static void main(String[] args) {
        InvocationHandler handler = new DynamicBuyHouse(new BuyHouseImpl());
        BuyHouse house = (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader(),new Class<?>[]{BuyHouse.class},handler);
        house.buyHouse();
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import proxy.Person;

public final class $Proxy0 extends Proxy implements Person
{
  private static Method m1;
  private static Method m2;
  private static Method m3;
  private static Method m0;
  
  /**
  *注意这里是生成代理类的构造方法,方法参数为InvocationHandler类型,看到这,是不是就有点明白
  *为何代理对象调用方法都是执行InvocationHandler中的invoke方法,而InvocationHandler又持有一个
  *被代理对象的实例,不禁会想难道是....? 没错,就是你想的那样。
  *
  *super(paramInvocationHandler),是调用父类Proxy的构造方法。
  *父类持有:protected InvocationHandler h;
  *Proxy构造方法:
  *    protected Proxy(InvocationHandler h) {
  *         Objects.requireNonNull(h);
  *         this.h = h;
  *     }
  *
  */
  public $Proxy0(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }
  
  //这个静态块本来是在最后的,我把它拿到前面来,方便描述
   static
  {
    try
    {
      //看看这儿静态块儿里面有什么,是不是找到了giveMoney方法。请记住giveMoney通过反射得到的名字m3,其他的先不管
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m3 = Class.forName("proxy.Person").getMethod("giveMoney", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
 
  /**
  * 
  *这里调用代理对象的giveMoney方法,直接就调用了InvocationHandler中的invoke方法,并把m3传了进去。
  *this.h.invoke(this, m3, null);这里简单,明了。
  *来,再想想,代理对象持有一个InvocationHandler对象,InvocationHandler对象持有一个被代理的对象,
  *再联系到InvacationHandler中的invoke方法。嗯,就是这样。
  */
  public final void giveMoney()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  //注意,这里为了节省篇幅,省去了toString,hashCode、equals方法的内容。原理和giveMoney方法一毛一样。

}

这就是那个动态生成的类,可以看出当他调用giveMoney()时,会调用父类的super.h.invoke(); h就是你传入的那个handler类,最后就是调用了你写的那个handler里面的invoke()方法,method也就是proxy调用的方法.

原文地址:https://www.cnblogs.com/lzh66/p/13288898.html