除了使用JDK方式产生动态代理外,Java还给我们提供了另外一种产生动态代理的方法,那就是使用cglib。

  cglib是这样实现动态代理的:

  · ①.针对类来实现代理

  · ②对指定目标类产生一个子类 ,通过方法拦截技术拦截所有父类方法的调用。

  ·

  cglib的实现机制与Java 动态代理不同,它是通过继承实现的 ,它也是动态创建了一个类,但这个类的父类是被代理的类,代理类重写了父类的所有public非final方法,改为调用Callback中的相关方法,在本例中,调用CglibProxy的intercept方法。

  具体实现步骤如下:

  1.我们先新建一个普通的Java项目,然后,在使用这个方法之前,我们需要给项目导入所需的jar包。

  cglib-nodep-2.2.jar

  2.建立被代理类

  package cglibProxy;

  public class Person {

  public void work(){

  System.out.println(工作中..);

  }

  }

  简单起见,我们这里只给Person类实现一个work()方法,用于模拟业务实现。

  3.接下来就是最重要的一点,建立代理类,代理类需要实现以下接口:

  interface MethodInterceptor{}

  这个接口需要我们导入jar包后才会出现,顾名思义,也就是方法拦截器。

  代理类的实现细节如下:

  package cglibProxy;

  import java.lang.reflect.Method;

  import net.sf.cglib.proxy.Enhancer;

  import net.sf.cglib.proxy.MethodInterceptor;

  import net.sf.cglib.proxy.MethodProxy;

  public class CglibProxy implements MethodInterceptor {

  private Enhancer enhancer = new Enhancer();

  public Object getProxy(Class clazz){

  //设置创建子类的类,即指定为哪个类产生代理类

  enhancer.setSuperclass(clazz);

  /*设置回调函数

  * setCallback设置被代理类的public非final方法被调用时的处理类

  * 这个例子中我们设置的方法为Person中的work()方法

  * 当work()方法被调用时,由该类进行处理

  * */

  enhancer.setCallback(this);

  //创建子类实例

  return enhancer.create();

  }

  /*

  * 作用:拦截所有目标类方法的调用

  * 参数:

  * 1. obj --目标类的实例对象

  * 2. method--目标方法的反射对象

  * 3. args --方法的参数

  * 4. proxy --代理类的实例对象

  * */

  @Override

  public Object intercept(Object obj, Method method, Object[] args,

  MethodProxy proxy) throws Throwable {

  System.out.println(代理类开始介入..);

  //代理类调用父类的方法

  proxy.invokeSuper(obj, args);

  System.out.println(代理类介入结束);

  return null;

  }

  }

  这里出现了一个比较少见的类Enhancer,查阅官方API,有这么一段注解:

  /*Generates dynamic subclasses to enable method interception.

  This class started as a substitute for the standard Dynamic Proxy

  support included with JDK 1.3, but one that allowed the proxies

  interfaces. The dynamically generated subclasses override

  the non-final methods of the superclass and have hooks which

  callback to user-defined interceptor implementations.*/

  翻译过来大概意思就是:

  /*生成动态子类以启用方法拦截。

  这个类开始替代了JDK 1.3中包含的标准动态代理支持,

  但是允许代理扩展一个具体的基类,以及实现接口。

  动态生成的子类覆盖超类的非最终方法,

  并具有回调到用户定义的拦截器实现的钩子。*/

  其实Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展。

  我们通过在代理类中聚合一个Enhancer类的一个实例对象,然后调用Enhancer实例对象的相应方法,对父类的调用方法进行拦截。

  代理类返回代理对象由getProxy()方法实现,其中:

  enhancer.setSuperclass(clazz);

  /*官方API对该类的注解如下:

  *Set the class which the generated class will extend.

  *翻译:

  *设置生成的类将要继承的类

  *这样比较难懂,从方法名中我们可以看出,这其实就是设置代理类的父类

  */

  与JDK动态代理不同,CglibProxy中没有被代理的对象,它通过MethodProxy类的实例对象proxy的invokeSuper方法调用被代理类的方法:

  proxy.invokeSuper(obj, args);

  但是,要注意的是,它不能这样调用被代理类的方法:

  proxy.invoke(obj, args);

  因为proxy是代理对象,调用这个方法还会调用到CglibProxy的intercept方法,造成死循环。

  3.最后,我们建立测试类

  package cglibProxy;

  public class Test {

  public static void main(String[] args) {

  //在main方法中,没有创建被代理的对象,创建的对象直接就是代理对象。

  CglibProxy proxy = new CglibProxy();

  //getProxy()方法返回代理方法产生的实例对象

  Person person = (Person)proxy.getProxy(Person.class);

  //代理对象调用wokr()方法

  person.work();

  }

  }

  运行结果:

  代理类开始介入..

  工作中..

  代理类介入结束

  动态代理是实现面向切面的编程(AOP – Aspect Oriented Programming)的基础,所以,了解动态代理的实现方法和机制是很有必要的,通过一个简单的实例,可以对动态代理有初步的认识,为以后的深入学习打下基础。

Cglib方法实现动态代理的更多相关文章

  1. 学习CGLIB与JDK动态代理的区别

    动态代理 代理模式是Java中常见的一种模式.代理又分为静态代理和动态代理.静态代理就是显式指定的代理,静态代理的优点是由程序员自行指定代理类并进行编译和运行,缺点是一个代理类只能对一个接口的实现类进 ...

  2. Cglib 与 JDK动态代理的运行性能比较

    都说 Cglib 创建的动态代理的运行性能比 JDK 动态代理能高出大概 10 倍,今日抱着怀疑精神验证了一下,发现情况有所不同,遂贴出实验结果,以供参考和讨论. 代码很简单,首先,定义一个 Test ...

  3. CGlib和JDK动态代理

    一.CGlib动态代理     JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了.CGLib采用了非常底层的1:字节码技术,其原理是通过字节 ...

  4. Cglib 与 JDK动态代理

    作者:xiaolyuh 时间:2019/09/20 09:58 AOP 代理的两种实现: jdk是代理接口,私有方法必然不会存在在接口里,所以就不会被拦截到: cglib是子类,private的方法照 ...

  5. 性能优于JDK代理,CGLib如何实现动态代理

    按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建 ...

  6. 死磕Spring之AOP篇 - 初识JDK、CGLIB两种动态代理

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  7. 面试造火箭系列,栽在了cglib和jdk动态代理

    "喂,你好,我是XX巴巴公司的技术面试官,请问你是张小帅吗".声音是从电话那头传来的 "是的,你好".小帅暗喜,大厂终于找上我了. "下面我们来进行一 ...

  8. 基于 CGLIB 库的动态代理机制

    之前的文章我们详细的介绍了 JDK 自身的 API 所提供的一种动态代理的实现,它的实现相对而言是简单的,但是却有一个非常致命性的缺陷,就是只能为接口中的方法完成代理,而委托类自己的方法或者父类中的方 ...

  9. java提供类与cglib包实现动态代理

    终于有点空余时间,决定把之前学习的知识点整理一下,备以后复习. 动态代理有三角色:抽象角色,代理角色,真是角色. 第一个记录下java提供的动态代理.即使用Proxy类和InvocationHande ...

随机推荐

  1. Fuzzy and fun on Air Jordan 12 Doernbecher design

    Carissa Navarro keeps it warm, fuzzy and fun on her 2017 Air Jordan 12 Doernbecher design. Nike's 20 ...

  2. http协议基础(九)响应首部字段

    响应首部字段: 服务器向客户端返回响应报文中所使用的字段,用于补充的附加信息.服务器信息.以及对客户端的附加要求等 1.Accept-Ranges 告知客户端服务器能否处理范围请求,以指定获取服务器的 ...

  3. 【upstream】Nginx配置upstream实现负载均衡

    如果Nginx没有仅仅只能代理一台服务器的话,那它也不可能像今天这么火,Nginx可以配置代理多台服务器,当一台服务器宕机之后,仍能保持系统可用.具体配置过程如下: 1. 在http节点下,添加ups ...

  4. 错误:Python Urlfetch Error:'GET

    1) 如果你初装了 GaAgent, 记得把在 proxy.ini 里的 id 填上:2) 刷新几次:3) 把浏览器关了,重新打开:4) 清除浏览器的缓冲区:5) 清除 cookies6) 用浏览器的 ...

  5. quartz开源作业调度框架的配置

    quartz开源作业调度框架的job服务实现,Quartz是一个完全由java编写的开源作业调度框架,使用时候需要创建一个实现org.quartz.Job接口的java类,Job接口包含唯一的方法: ...

  6. Win10安装MySQL5.7.22 解压缩版(手动配置)方法

    1.下载地址:https://dev.mysql.com/downloads/mysql/5.7.html#downloads 直接点击下载项 下载后: 2.可以把解压的内容随便放到一个目录,我的是如 ...

  7. linux基础命令---touch

    touch 将文件的访问时间和修改时间修改为当前时间.如果指定的文件不存在,那么将会创造空文件,除非指定-c或-h选项.文件参数字符串‘-‘被专门处理,并导致touch更改与标准输出相关联的文件的时间 ...

  8. Python Web学习笔记之图解TCP/IP协议和浅析算法

    本文通过两个图来梳理TCP-IP协议相关知识.TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道.如图1所示,给出了TCP通信过程的示意图. 图1主要包括三部分:建立连接.传 ...

  9. cache与buffer

    Cache 缓存区,是高速缓存,是位于CPU和主内存之间的容量较小但速度很快的存储器,因为CPU的速度远远高于主内存的速度,CPU从内存中读取数据需等待很长的时间,而  Cache保存着CPU刚用过的 ...

  10. Python3基础 __doc__ 单行与多行函数文档

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...