快捷搜索:  汽车  科技

动态代理两种实现方式(如何理解动态代理机制)

动态代理两种实现方式(如何理解动态代理机制)优点://厂家商家都要实现的功能 public interface UsbSaleService { //提供买U盘的数量,返回价格 float sell(int i); } //厂家,不接受用户直接购买 class UsbFactory implements UsbSaleService{ @Override public float sell(int i) { //厂家发货,一个2GU盘20元 return i*20f; } } //商家,代理U盘的销售 class Taobao implements UsbSaleService{ //指定代理的厂家 private UsbFactory usbFactory=new UsbFactory(); @Override public f

生活中的代理

例子:比如一家美国大学,可以对全世界招生,留学中介就是代理,帮美国大学招生。


代理的特点
  1. 中介和他们代理的做事是一样:招生。
  2. 中介是学校的代理,学校是目标。
  3. 流程为,家长->中介->学校。
  4. 中介是代理,需要收取费用。

为什么找代理
  1. 中介是专业的。
  2. 家长没有办法接触到学校。

开发中的代理

例子1:A类想调用C类,但是C类禁止访问,只能在AC中间创建B类作为代理。 C的结果给B,B给A。


例子2:登录需要手机验证码,我们没有能力发送短信,移动联通有能力发短信。 移动联通有子公司提供发送短信的业务,于是我们->子公司->移动联通发短信。


代理模式代理模式的定义

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。


代理模式的作用
  1. 功能增强:在你原有的功能上新增加功能。
  2. 控制访问:代理类不让你访问目标类。
代理的实现方式静态代理
  • 代理类是自己手工实现的。
  • 代理的目标是确定的。
  • 特点:实现简单,容易理解。

例子:用户购买U盘,商家代理某个品牌的U盘。商家卖U盘,厂家提供。用户(客户端)->代理类(商家)->目标(厂家)。

步骤:

  1. 创建接口实现卖U盘的方法,即厂家和商家要做的事情。
  2. 创建商家类实现卖U盘的方法。
  3. 创建厂家类实现卖U盘的方法。
  4. 创建一个客户端类,调用商家方法去买U盘。

代码:

//厂家商家都要实现的功能 public interface UsbSaleService { //提供买U盘的数量,返回价格 float sell(int i); } //厂家,不接受用户直接购买 class UsbFactory implements UsbSaleService{ @Override public float sell(int i) { //厂家发货,一个2GU盘20元 return i*20f; } } //商家,代理U盘的销售 class Taobao implements UsbSaleService{ //指定代理的厂家 private UsbFactory usbFactory=new UsbFactory(); @Override public float sell(int i) { //向厂家发送订单,厂家发货 //代理加价,一个U盘加10元,增强功能 return usbFactory.sell(i) i*10f; } } //用户购买 class shop{ public static void main(String[] args) { //控制访问 Taobao taobao=new Taobao(); System.out.println(taobao.sell(5)); } }


静态代理优缺点: 缺点:

  1. 目标类增加,代理类会成倍的增加,即代理类数量过多。
  2. 功能类增加方法后导致目标类、代理类都需要修改,影响较大。

优点:

  1. 功能增强。
  2. 访问控制,解耦。
动态代理

在程序执行过程中,使用JDK反射机制,创建代理类对象,并动态的指定要代理的目标类,无需用户创建对象。

总结

动态代理两种实现方式(如何理解动态代理机制)(1)

复习反射

import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class InflectTest { public static void main(String[] args) throws NoSuchMethodException InvocationTargetException IllegalAccessException { /*创建对象执行 helloImpl hello=new helloImpl(); hello.sayHello("张三"); */ /*通过反射执行 Hello h=new HelloImpl(); Method method=Hello.class.getMethod("sayHello" String.class); Object res=method.invoke(h "李四"); */ } } class HelloImpl implements Hello{ @Override public void sayHello(String name) { System.out.println("你好," name); } } interface Hello{ public void sayHello(String name); }如何实现动态代理

动态代理两种实现方式(如何理解动态代理机制)(2)


动态代理两种实现方式(如何理解动态代理机制)(3)


动态代理两种实现方式(如何理解动态代理机制)(4)


动态代理两种实现方式(如何理解动态代理机制)(5)


//参数1:jdk提供的代理对象无需赋值 //参数2:jdk提供的目标类的方法 //参数3:目标类方法的参数 public Object invoke(Object proxy Method method Object[] args) throws Throwable; 复制代码

动态代理两种实现方式(如何理解动态代理机制)(6)


动态代理两种实现方式(如何理解动态代理机制)(7)


案例一:

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Random; interface Moveable { void move(); } public class Car implements Moveable { @Override public void move() { try { Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } class Timehandler implements InvocationHandler { public TimeHandler(Object target) { super(); this.target = target; } private Object target; @Override public Object invoke(Object proxy Method method Object[] args) throws Throwable { long starttime = System.currentTimeMillis(); method.invoke(target); long endtime = System.currentTimeMillis(); System.out.println("汽车行驶时间:" (endtime - starttime) "毫秒!"); return null; } } class Test { public static void main(String[] args) { Car car = new Car(); InvocationHandler h = new TimeHandler(car); Class<?> cls = car.getClass(); Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader() cls.getInterfaces() h); m.move(); } }

动态代理两种实现方式(如何理解动态代理机制)(8)

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface UsbSell{ float sell(int sum); } class Factory implements UsbSell{ @Override public float sell(int sum) { return sum*100f; } } class MySellHandle implements InvocationHandler{ private Object target; MySellHandle(Object target){ this.target=target; } @Override public Object invoke(Object proxy Method method Object[] args) throws Throwable { Object res=method.invoke(target args); return (Float)res (int)args[0]*5; } } public class JDKModel { public static void main(String[] args) { UsbSell usbSell=new Factory(); InvocationHandler handler=new MySellHandle(usbSell); UsbSell proxy=(UsbSell) Proxy.newProxyInstance(usbSell.getClass().getClassLoader() usbSell.getClass().getInterfaces() handler); System.out.println(proxy.sell(10)); } }实际开发中动态代理的应用


JDK动态代理,必须有接口。 CGLib动态代理,必须能被继承,即class不能是 final。


我在校大二期间接过私活,一元秒杀抢购系统。 这个系统有两个特点,一没有文档,二没有源码。只有一堆运行在Tomcat上的class文件和html文件。除了新增的CUID等功能外,还要调用之前人写的代码。因为不敢动之前人写的代码,所以就先反编译,然后继承重写指定方法,测试没问题后在修改AJAX的URL。上一个人不开发了,所以不用考虑代码变动问题。最主要的是发现要重写的太多了,评估了一下工作量,要继承重写几十个ServiceImpl,后来就直接用动态代理来做的。


作者:比卷帘门还能卷
链接:https://juejin.cn/post/7044907218050744328

猜您喜欢: