除了使用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. 集成学习ensemble

    集成学习里面在不知道g的情况下边学习边融合有两大派:Bagging和Boosting,每一派都有其代表性算法,这里给出一个大纲. 先来说下Bagging和Boosting之间的相同点:都是不知道g,和 ...

  2. excel 批量在一列数据添加单引号以及逗号

    在A列后插入一列B1输入="'"&a1&"'," 然后向下填充 就ok 了 向下填充:选中上方连续单元格,鼠标放在选中区域右下角处(会显示“十” ...

  3. CMPXCHG指令

    一.CMPXCHG汇编指令详解. 这条指令将al\ax\eax\rax中的值与首操作数比较: 1.如果相等,第2操作数的直装载到首操作数,zf置1.(相当于相减为0,所以0标志位置位) 2.如果不等, ...

  4. STA分析(二) multi_cycle and false

    multicycle path:当FF之间的组合逻辑path propagate delay大于一个时钟cycle时,这条combinational path能被称为multicycle path. ...

  5. css+table

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 浅谈CDN加速问题

    (以百度CDN进行分析) 婆说婆有理,公说公有理.是否使用CDN,不同的工程师有不同的意见. 这里呢我来进行一下简单的分析. [正方观点] 1. 提升网站加载速度:CDN通过缓存技术提升网站打开速度, ...

  7. Linux 使用系统ISO制作yum源

    关于linux安装问题,大多数情况下 系统开发完成之后,需要部署到生产机器上,客户提供的机器预装好了操作系统,但是都是内网环境 与外网都是物理隔绝的,那么 在搭建生产环境时需要安装相关软件时,如果自己 ...

  8. Solr安装中文分词器IK

    安装环境 jdk1.7 solr-4.10.3.tgz KAnalyzer2012FF_u1.jar tomcat7 VM虚拟机redhat6.5-x64:192.168.1.201 Xshell4 ...

  9. MySQL Crash Course #05# Chapter 9. 10. 11. 12 正则.函数. API

    索引 正则表达式:MySQL only supports a small subset of what is supported in most regular expression implemen ...

  10. Web前端学习笔记之安装和使用PhantomJS

    0x00 安装PhantomJS(linux环境安装) 将PhantomJS下载在/usr/local/src/packet/目录下(这个看个人喜好) 操作系统:CentOS 7 64-bit 1.下 ...