设计模式简介意图:为其他对象提供代理,控制对整个对象的访问。主要解决:直接访问对象带来的问题,例如:要访问的对象在远程机器上。在面向对象的系统中,由于某些原因(比如对象创建成本很高,或者某些操作需要安全控制,或者需要进程外访问),直接访问会给用户或者系统结构带来很多麻烦,我们可以在访问这个对象的时候给这个对象加上一个访问层。优点:职责明确智能可扩展性强缺点:由于在客户端和真实主体之间增加了代理对象,某些类型的代理模型可能会减慢请求的处理速度。实施代理需要额外的工作,而且一些代理模式实施起来非常复杂。使用场景:远程代理虚拟代理Copy-on-Write代理保护代理缓存代理防火墙代理同步代理智能引用代理实现静态代理静态代理需要定义一个接口或者父类,代理对象和代理对象共同实现接口或继承相同的父类。接口interfaceMovable{voidmove();}是实现接口move方法的代理类publicclassTankimplementsMovable{/***模拟坦克移动一段时间*/@Overridepublicvoidmove(){System.出去。println("Tankmovingclaclacla...");尝试{Thread.sleep(newRandom().nextInt(10000));}catch(InterruptedExceptione){e.printStackTrace();代理类也实现了这个Interface,添加了Movable属性,实现了move方法内部调用传入的代理类的move方法,可以在调用前后添加一些业务代码。类TankTimeProxy实现Movable{Movablem;publicTankTimeProxy(Movablem){this.m=m;}@Overridepublicvoidmove(){longstart=System.currentTimeMillis();m.移动();长端=System.currentTimeMillis();System.out.println(结束-开始);}}最后在main方法中调用代理类的move方法。如果需要多个代理类,可以使用多层嵌套类Demo{publicstaticvoidmain(String[]args){Tankt=newTank();TankTimeProxyttp=newTankTimeProxy(t);//坦克日志代理tlp=newTankLogProxy(ttp);ttp.move();}}静态代理总结:可以在不修改目标对象的功能的情况下扩展目标功能缺点:因为代理对象需要和目标对象有相同的接口,所以会出现很多类型过多的代理类.同时,一旦方法被添加到接口中,目标对象和代理对象都必须维护。动态代理特点:代理对象不需要实现接口代理对象的生成。它们使用JDKAPI在内存中动态构建代理对象(cglibproxywithoutinterfaces)。代理类实现接口move方法publicclassTankimplementsMovable{/***模拟坦克移动一段时间*/@Overridepublicvoidmove(){System.out.println("Tankmovingclaclacla...");尝试{Thread.sleep(newRandom().nextInt(10000));}catch(InterruptedExceptione){e.printStackTrace();}}}JDK代理:代理类所在包:java.lang.reflect.ProxypublicstaticObjectnewProxyInstance(ClassLoaderloader,Class>[]interfaces,InvocationHandlerh)ClassLoaderloader:指定当前要使用的目标对象类加载器Class>[]interfaces:目标对象实现的接口类型InvocationHandlerh:事件处理,当目标对象的方法执行时,会触发事件处理器,并将其传递给方法当前执行的目标对象作为参数传入接口interfaceMovable{voidmove();}被代理,实现接口move方法publicclassTankimplementsMovable{/***模拟坦克移动一段时间*/@Overridepublicvoidmove(){System.out.println("Tankmovingclacla...");尝试{Thread.sleep(新随机().nextInt(10000));}catch(InterruptedExceptione){e.printStackTrace();}}}创建代理类调用处理程序classTimeProxyimplementsInvocationHandler{//代理类中的真实对象Movablem;publicTimeProxy(Movablem){this.m=m;}publicvoidbefore(){System.out.println("方法开始..");}publicvoidafter(){System.out.println("方法停止..");}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{before();对象o=method.invoke(m,args);后();返回o;}}Demo调用生成指定接口的代理类实例publicstaticvoidmain(String[]args){Tanktank=newTank();Movablem=(Movable)Proxy.newProxyInstance(Tank.class.getClassLoader(),newClass[]{Movable.class},//tank.class.getInterfaces()newTimeProxy(tank));m.move();}上面的演示生成了指定接口的代理类示例,但是在JDK中,通过JDKProxies或者cglib代理是在运行时自动生成的JDK在内存中动态代理生成动态代理文件的原理方法一:必须在main方法中执行,直接使用junit测试方法调用不能生成JDK1.8之后,在主要方法前面"jdk.proxy.ProxyGenerator.saveGeneratedFiles","true");JDK1.8和之前添加System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");在主要方法的前面;方法二:运行时添加jvm参数-Djdk.proxy.ProxyGenerator.saveGeneratedFiles=true。运行时添加jvm参数-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true。代理类的class文件会在当前目录的com包中生成。然后。..这是源代码过程。首先把上图截图,发现图片太多了。..Movablem=(Movable)Proxy.newProxyInstance(Tank.class.getClassLoader(),newClass[]{Movable.class},newTimeProxy(tank));/**查找或生成指定代理类及其构造函数。*/构造函数>cons=getProxyConstructor(caller,loader,interfaces);returnproxyCache.sub(intf).computeIfAbsent(loader,(ld,clv)->newProxyBuilder(ld,clv.key()).build());Constructor>build(){Class>proxyClass=defineProxyClass(module,interfaces);最终构造函数>缺点;尝试{cons=proxyClass.getConstructor(constructorParams);}catch(NoSuchMethodExceptione){thrownewInternalError(e.toString(),e);}AccessController.doPrivileged(newPrivilegedAction
