java动态代理源码分析,JAVA动态代理-简书

  java动态代理源码分析,JAVA动态代理-简书

  00-1010代理模式静态代理动态代理JDK动态代理CGLIB动态代理JDK代理和CGLIB代理的区别‘代理’大家都不陌生。简单来说就是代替厂家卖货,代理商代替厂家卖货,客户找代理商进货。也就是说:1)客户和厂家的关系是隐形的,客户不知道厂家背后是谁。2)代理商可以“定位”客户,更精准地销售给需要的客户群体。

  00-1010代理模式:为其他对象提供代理来控制对该对象的访问,即创建一个代理对象作为客户端和目标对象之间的中介,主要目的是保护或增强目标对象。

  通过使用代理模式,通常有以下两个优点:

  1)您可以隐藏代理类的实现。

  2)可以实现客户端和主体类的解耦,不需要修改主体类的代码就可以做一些额外的处理。

  00-1010所谓动态代理,就是通过声明一个显式的代理类来访问源对象。一个代理只能服务一个产品,有n个产品的时候就需要n个代理,不利于业务的开展。

  比如我们有两个接口,鼠标和键盘,每个接口都有一个实现类。

  实现中的代码如下:

  类罗技鼠标实现Mouse { @ override public void sell(){ system . out . println( selling罗技鼠标);}}公共类HHKBKeyboard实现Keyboard { @ override Public void sell(){ system . out . println(出售HHKB键盘);}}}现在我们要做的就是让代理商在打电话之前输出一句售前理解句,打电话之后输出一句售后服务句。

  然后我们只需要写两个代理类,MouseProxy和KeyboardProxy。

  公共类MouseProxy实现Mouse { private Mouse mousepublic Mouse proxy(Mouse Mouse){ this . Mouse=Mouse;} @ override public void sell(){ system . out . println(售前知识);mouse . sell();System.out.println(“售后服务”);} }公共类KeyboardProxy实现键盘{ private Keyboard keyboardpublic Keyboard proxy(Keyboard Keyboard){ this . Keyboard=Keyboard;} @ override public void sell(){ system . out . println(售前知识);keyboard.sell()。System.out.println(“售后服务”);}}最后执行的是:

  public class Test { public static void main(String[]args){ Mouse logitechMouse=new logitechMouse();mouse proxy mouse proxy=new mouse proxy(logitechMouse);mouse proxy . sell();keyboard hhkbKeyboard=new hhkbKeyboard();keyboard proxy keyboard proxy=new keyboard proxy(hhkbKeyboard);keyboard proxy . sell();}}}输出:售前了解卖罗技鼠标售后服务售前了解卖HHKB键盘售后服务

  静态代理的代码非常简单易懂。这种模式虽然好,但也有明显的缺点:

  将会有大量冗余的代理类。这里只有两个接口。如果有n个接口,那么就需要定义n个代理类。维护起来并不容易。一旦接口改变,代理类和代理类都必须改变。所以这个

  个时候就可以使用动态代理来解决了

  

 

  

动态代理

代理类在程序运行时创建代理的方式叫动态代理,也就是说代理类并不是在java代码中定义的,而是在运行的时候动态生成的

 

  

 

  

JDK动态代理

JDK从1.3版本就开始支持动态代理类的创建。主要核心类只有2个:java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler

 

  还是上面的例子,用JDK动态代理如下:

  

public class JDKProxy implements InvocationHandler { private Object object; public JDKProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("售前了解"); Object invoke = method.invoke(object, args); System.out.println("售后服务"); return invoke; }}

当我们调用代理类对象的方法时,这个调用会转送到invoke方法中,

 

  代理类对象作为proxy参数传入,

  参数method标识了我们具体调用的是代理类的哪个方法,

  args为这个方法的参数。

  这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。因此我们可以在中介类的invoke方法中实现输出售前了解,再调用被代理类的方法,再输出售后服务。

  

 

  执行代码

  

public class Test { public static void main(String[] args) { Mouse logitechMouse = new LogitechMouse(); JDKProxy jdkProxy = new JDKProxy(logitechMouse); Mouse mouse= (Mouse)Proxy.newProxyInstance(jdkProxy.getClass().getClassLoader(), new Class[]{Mouse.class}, jdkProxy); mouse.sell(); HHKBKeyboard hhkbKeyboard = new HHKBKeyboard(); JDKProxy jdkProxy1 = new JDKProxy(hhkbKeyboard); Keyboard keyboard = (Keyboard)Proxy.newProxyInstance(jdkProxy1.getClass().getClassLoader(), new Class[]{Keyboard.class}, jdkProxy1); keyboard.sell(); }}

可以看到无论多少个接口,只需要一个代理类就可以了。

 

  

 

  

CGLIB动态代理

代理类:

 

  

public class CGLIBProcy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); private Object object; public CGLIBProcy(Object object) { this.object = object; } public Object getProxy(){ //设置需要创建子类的类 enhancer.setSuperclass(object.getClass()); enhancer.setCallback(this); //创建代理对象 return enhancer.create(); } // o: cglib 动态生成的代理类的实例 // method:实体类所调用的都被代理的方法的引用 // objects 参数列表 // methodProxy:生成的代理类对方法的代理引用 @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("售前了解"); Object invoke = method.invoke(object, objects); System.out.println("售后处理"); return invoke; }}

执行代码:

 

  

public class Test { public static void main(String[] args) { Mouse logitechMouse = new LogitechMouse(); CGLIBProcy cglibProcy = new CGLIBProcy(logitechMouse); Mouse proxy = (Mouse)cglibProcy.getProxy(); proxy.sell(); cglibProcy = new CGLIBProcy(new HHKBKeyboard()); Keyboard keyboard = (Keyboard)cglibProcy.getProxy(); keyboard.sell(); }}

 

  

JDK代理与CGLIB代理的区别

JDK动态代理实现接口,CGLIB动态继承思想JDK动态代理(目标对象存在接口时)执行效率高于CIGLIB如果对象有接口实现,选择JDK代理,如果没有接口实现选择CGILB代理到此这篇关于Java深入分析动态代理的文章就介绍到这了,更多相关Java动态代理内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: