05、人人都会设计模式:代理模式--Proxy( 三 )


好了,上面我们看到我们使用代理类直接继承了真实的类「这也是代理的一个变种」,但是根据多用类组合少用继承的规则,我们还是少用这种继承形式的代理
以上是静态代理,静态代理有局限性,想如果悟空多了项技能,六耳猕猴就得学此项技能「感觉很像我们搞技术的,技术日新月异,得不断的学习才能进步」
静态代理的缺点:
2、使用动态代理完成
动态代理就是代理类不是在代码中定义的,而是根据我们的指示动态生成的「通过反射机制动态生成代理者对象」,在编码阶段,你从代码上根本不知道谁代理谁,具体代理谁,好吧太绕了,直接看代码
1、Proxy 类
说动态代理之前,我们先来看看 Java 中提供的 Proxy 类
看看这个类的注释一部分
/* {@code Proxy} provides static methods for creating dynamic proxy* classes and instances, and it is also the superclass of all* dynamic proxy classes created by those methods.* .....*/public class Proxy implements java.o.Serializable {.... 省略代码 }
从注释可以看出 Proxy 提供一些静态方法来创建动态代理类和实例
Proxy 简单的 UML
Proxy 主要方法讲解
Proxy 主要方法就是这个方法
public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h){... // 省略若干代码 // 取得代理类Class cl = getProxyClass0(loader, intros)... // 省略若干代码 // 调用代理类的构造方法final Constructor cons = cl.getConstructor(constructorParams);... // 省略若干代码 final InvocationHandler ih = h;... // 省略若干代码 // 通过代理类的构造方法生成代理类的实例return cons.newInstance(new Object[]{h});}
其中三个参数:
public interface InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;}
其中三个参数:
接口中的方法就是执行被代理对象中的方法
2、使用动态代理修改真假美猴王代码
动态代理悟空 简单的UML
根据 UML 撸码
只需要在原有代码的基础上添加一个动态类并且删掉六耳猕猴类「动态代理来了,小六你还不快撤」,然后修改 Test 即可
/*** 动态代理类*/public class ToWestProxy implements InvocationHandler {// 需要代理的对象即真实对象private Object delegate ;public Object getProxy(Object delegate){this.delegate = delegate ;// 动态构建一个代理returnProxy.newProxyInstance(delegate.getClass().getClassLoader(),delegate.getClass().getInterfaces(),this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return method.invoke(delegate,args) ; // 通过反射调用真实对象对应的方法}}
我们看到上在被代理的对象是一个类型,所以可以看出这个代理类就是一个万能的代理,不仅仅可以代理悟空,牛魔王也能代理「扯远了」
/*** Created by TigerChain* 测试类*/public class Test {public static void main(String args[]){IToWest sunWuKong = new SunWuKong() ;// 取得动态代理IToWest proxy = (IToWest) new ToWestProxy().getProxy(sunWuKong);proxy.baohuTangSeng();proxy.xiangYaoChuMo();proxy.shangTianRuDi();System.out.println("我孙悟空能去得了西天");}}
看到了,真实对象悟空随便你改,我再添加接口,方法,我动态代理不用动「如果是静态代理六耳猕猴,那就得随着悟空的修改必须得修改自己」
而且,我们还可以得出,这个动态代理不仅仅可以代理悟空,简直可以代理一切对象「不信你定义一个牛魔王试试」