代理模式
代理模式:某个代理对象和真实对象都实现同一个接口,代理对象有真实对象的引用,实现的业务还是有真实对象来完成,但是代理对象可以在实现业务加一些别的代码。
静态代理
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调用的方法.