1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法。

CGLIB动态代理:

使用JDK的Proxy实现代理,要求目标类与代理类实现相同的接口。若目标类不存在接口,则无法使用该方式实现。

但对于无接口的类,要为其创建动态代理类,就要使用CGLIB来实现。CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类必须能够被继承,即不能是final的类。

CGLIB(Code Generation Library)是一个开源项目,是一个强大的、高性能的、高质量的代码生成类库。它可以在运行期扩展喝增强Java类。Hibernate用它来实现持久对象的字节码的动态生成,Spring用它来实现AOP编程。

CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM(Java字节码操控框架)来转换字节码并生成新的类。CGLIB是通过对字节码进行增强来生成代理的。

代理实现与解析:

使用CGLIB创建代理步骤:

步骤1:导入CGLIB的Jar包:cglib-full.jar。

步骤2:定义目标类。注意不用实现任何接口。

public class AccountService {//目标方法public void transfer(){System.out.println("调用Dao层,完成转账主业务。");}//目标方法public void getBalance(){System.out.println("调用Dao层,完成查询余额主业务。");}//该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的final public void others() {System.out.println("调用Dao层,完成其它主业务。");}}

步骤3:创建代理类的工厂。该类要实现MethodInterceptor接口。

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;//自定义MethodInterceptor
public class CglibProxyDemo implements MethodInterceptor {/** All generated proxied methods call this method instead of the original method. The original method may either be invoked by normal reflection using the Method object, or by using the MethodProxy (faster).     * @param obj "this", the enhanced object     * @param method intercepted Method     * @param args argument array; primitive types are wrapped     * @param proxy used to invoke super (non-intercepted method); may be called as many times as needed     * @throws Throwable any exception may be thrown; if so, super method will not be invoked     * @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.     * @see MethodProxy* * intercept()方法中各参数的意义* proxy:代理对象;表示增强的对象,即实现这个接口类的一个对象,cglib生成的代理对象;* method:被代理对象的方法* args[]:方法参数;拦截方法的参数* methodProxy:代理对象方法的代理对象* */@Overridepublic Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {System.out.println("=========进入CGLIB代理=========");Object result = null;// 若为transfer方法,则进行增强if("transfer".equals(method.getName())){System.out.println("===前置处理时间:" + System.currentTimeMillis());result = methodProxy.invokeSuper(proxy, args);System.out.println("===后置处理时间:" + System.currentTimeMillis());return result;}return methodProxy.invokeSuper(proxy, args);}
}

步骤4:创建测试类。

import net.sf.cglib.core.DebuggingClassWriter;
import java.io.IOException;
import net.sf.cglib.proxy.Enhancer;
import com.proxyDemo.cglibProxy.service.TargetService;
import com.proxyDemo.cglibProxy.service.CglibProxyDemo;public class CglibMainDemo {public static void main(String[] args) throws IOException {// 代理类class文件存入本地磁盘方便我们反编译查看源码System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");//创建增强器Enhancer enhancer = new Enhancer();//初始化增强器:将目标类指定为父类enhancer.setSuperclass(new TargetService().getClass());//初始化增强器:设置回调enhancer.setCallback(new CglibProxyDemo());//通过Enhancer.create()方法创建代理对象TargetService service = (TargetService) enhancer.create();//通过代理对象调用目标方法service.transfer();service.getBalance();service.others();}
}

查看生成代理对象反编译后代码如下:

import java.lang.reflect.Method;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class TargetService$$EnhancerByCGLIB$$bde35d74 extends TargetServiceimplements Factory
{private boolean CGLIB$BOUND;private static final ThreadLocal CGLIB$THREAD_CALLBACKS;private static Callback[] CGLIB$DEFAULT_CALLBACKS;private MethodInterceptor CGLIB$CALLBACK_0;private static final Method CGLIB$transfer$0$0$Method;private static final MethodProxy CGLIB$transfer$0$0$Proxy;private static final Object[] CGLIB$emptyArgs;private static final Method CGLIB$getBalance$0$1$Method;private static final MethodProxy CGLIB$getBalance$0$1$Proxy;private static final Method CGLIB$finalize$0$2$Method;private static final MethodProxy CGLIB$finalize$0$2$Proxy;private static final Method CGLIB$equals$0$3$Method;private static final MethodProxy CGLIB$equals$0$3$Proxy;private static final Method CGLIB$toString$0$4$Method;private static final MethodProxy CGLIB$toString$0$4$Proxy;private static final Method CGLIB$hashCode$0$5$Method;private static final MethodProxy CGLIB$hashCode$0$5$Proxy;private static final Method CGLIB$clone$0$6$Method;private static final MethodProxy CGLIB$clone$0$6$Proxy;static void CGLIB$STATICHOOK1(){CGLIB$THREAD_CALLBACKS = new ThreadLocal();Class localClass;CGLIB$emptyArgs = new Object[0];ClassLoader tmp27_17 = (localClass = Class.forName("com.proxyDemo.cglibProxy.service.TargetService$$EnhancerByCGLIB$$bde35d74")).getClassLoader();CGLIB$transfer$0$0$Proxy = MethodProxy.create(tmp27_17, (bde35d74.CGLIB$transfer$0$0$Method = Class.forName("com.proxyDemo.cglibProxy.service.TargetService").getDeclaredMethod("transfer", new Class[0])).getDeclaringClass(), localClass, "()V", "transfer", "CGLIB$transfer$0$0");ClassLoader tmp62_27 = tmp27_17;CGLIB$getBalance$0$1$Proxy = MethodProxy.create(tmp62_27, (bde35d74.CGLIB$getBalance$0$1$Method = Class.forName("com.proxyDemo.cglibProxy.service.TargetService").getDeclaredMethod("getBalance", new Class[0])).getDeclaringClass(), localClass, "()V", "getBalance", "CGLIB$getBalance$0$1");ClassLoader tmp97_62 = tmp62_27;CGLIB$finalize$0$2$Proxy = MethodProxy.create(tmp97_62, (bde35d74.CGLIB$finalize$0$2$Method = Class.forName("java.lang.Object").getDeclaredMethod("finalize", new Class[0])).getDeclaringClass(), localClass, "()V", "finalize", "CGLIB$finalize$0$2");ClassLoader tmp132_97 = tmp97_62;CGLIB$equals$0$3$Proxy = MethodProxy.create(tmp132_97, (bde35d74.CGLIB$equals$0$3$Method = Class.forName("java.lang.Object").getDeclaredMethod("equals", new Class[] { Class.forName("java.lang.Object") })).getDeclaringClass(), localClass, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$0$3");ClassLoader tmp175_132 = tmp132_97;CGLIB$toString$0$4$Proxy = MethodProxy.create(tmp175_132, (bde35d74.CGLIB$toString$0$4$Method = Class.forName("java.lang.Object").getDeclaredMethod("toString", new Class[0])).getDeclaringClass(), localClass, "()Ljava/lang/String;", "toString", "CGLIB$toString$0$4");ClassLoader tmp210_175 = tmp175_132;CGLIB$hashCode$0$5$Proxy = MethodProxy.create(tmp210_175, (bde35d74.CGLIB$hashCode$0$5$Method = Class.forName("java.lang.Object").getDeclaredMethod("hashCode", new Class[0])).getDeclaringClass(), localClass, "()I", "hashCode", "CGLIB$hashCode$0$5");CGLIB$clone$0$6$Proxy = MethodProxy.create(tmp210_175, (bde35d74.CGLIB$clone$0$6$Method = Class.forName("java.lang.Object").getDeclaredMethod("clone", new Class[0])).getDeclaringClass(), localClass, "()Ljava/lang/Object;", "clone", "CGLIB$clone$0$6");return;}final void CGLIB$transfer$0$0(){super.transfer();}public final void transfer(){MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;if (tmp4_1 == null){tmp4_1;CGLIB$BIND_CALLBACKS(this);}if (this.CGLIB$CALLBACK_0 != null)return;super.transfer();}......public final void getBalance(){MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;if (tmp4_1 == null){tmp4_1;CGLIB$BIND_CALLBACKS(this);}if (this.CGLIB$CALLBACK_0 != null)return;super.getBalance();}............static{CGLIB$STATICHOOK1();}
}

从代理对象反编译源码可以知道,代理对象继承于TargetService

希望对你有帮助,祝你有一个好心情,加油!

若有错误、不全、可优化的点,欢迎纠正与补充!

代理模式-CGLIB动态代理相关推荐

  1. cglib动态代理jar包_代理模式详解:静态代理+JDK/CGLIB 动态代理实战

    1. 代理模式 代理模式是一种比较好的理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标 ...

  2. 代理详解 静态代理+JDK/CGLIB 动态代理实战

    1. 代理模式 代理模式是一种比较好理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对 ...

  3. Java拾遗:007 - 代理模式与动态代理

    2019独角兽企业重金招聘Python工程师标准>>> 代理模式 在日常开发中我们可以会接手一些老的项目,有时连源码都没有,或者有时候我会需要对业务逻辑做一定增强(功能扩展,如:日志 ...

  4. 一文理解JDK静态代理、JDK动态代理、Cglib动态代理

    代理模式 通过代理来访问真实的对象,而不是直接去访问真正干活的对象,比如二房东租房,二房是代理者,而一房东才是真正的房东:或者说生活中的中介.Spring中的AOP就是动态代理 适用场景 需要动态修改 ...

  5. 浅谈Spring中JDK动态代理与CGLIB动态代理

    前言 Spring是Java程序员基本不可能绕开的一个框架,它的核心思想是IOC(控制反转)和AOP(面向切面编程).在Spring中这两个核心思想都是基于设计模式实现的,IOC思想的实现基于工厂模式 ...

  6. Java 静态代理、Java动态代理、CGLIB动态代理

    为什么80%的码农都做不了架构师?>>>    Java 的代理就是客户类不再直接和委托类打交道, 而是通过一个中间层来访问, 这个中间层就是代理.为啥要这样呢, 是因为使用代理有 ...

  7. Java静态代理、动态代理以及CGLIB动态代理

    代理模式是java中最常用的设计模式之一,尤其是在spring框架中广泛应用.对于java的代理模式,一般可分为:静态代理.动态代理.以及CGLIB实现动态代理. 对于上述三种代理模式,分别进行说明. ...

  8. 静态代理,JDK动态代理,Cglib动态代理详解

    目录 一.代理模式 二.静态代理 三.动态代理 3.1 JDK动态代理 3.2 Cglib动态代理 四.两种动态代理区别 一.代理模式 代理模式(Proxy Pattern)是程序设计中的一种设计模式 ...

  9. 谁与争锋,JDK动态代理大战CGLib动态代理

    文章目录 一.前言 二.基本概念 三.JDK 和 CGLib动态代理区别 3.1 JDK动态代理具体实现原理 3.2 CGLib动态代理 3.3 两者对比 3.4 使用注意 四.JDK 和 CGLib ...

  10. Java内功修炼系列:代理模式及动态代理

    目录 一 代理模式 1.1 简介 1.2 代理模式角色定义 二 静态代理 2.1 介绍和实例 2.2 静态代理的缺点 三 动态代理 3.1 基于JDK原生动态代理实现 四 小结 一 代理模式 1.1 ...

最新文章

  1. 【Spark】Spark2.x版的新特性
  2. 运维工程师的职责和前景
  3. http方法_像本地方法一样调用http服务,feign框架springboot项目实践
  4. STM 32 窗口看门狗
  5. GRIDVIEW排序 动态实现和静态实现
  6. oracle数据库表excel文件位置,Excel数据导入到oracle数据库表方法
  7. 简单php web ftp服务器,php 上传文件到ftp服务器的简单示例(单文件)
  8. echo 多行_分享laravel-echo-server广播服务搭建-Laravel
  9. matlab鲍威尔方法求函数,基于MATLAB的鲍威尔法求极值问题.doc
  10. 3D材质管理软件Adobe Substance 3D Sampler中文版
  11. win7 计算机登录用户名和密码忘记,电脑win7登陆密码忘记了怎么办_win7忘记登陆密码如何进入-win7之家...
  12. 黑苹果Win与Mac时间同步工具
  13. 计算机大赛鼓励语录,比赛前的鼓励的话
  14. 从0-1的CTF比赛环境搭建过程
  15. 经常写大材料的请惠存(转载)
  16. tensorflow报错Can not squeeze dim[1], expected a dimension of 1, got n for解决办法
  17. 毕业设计-后台管理系统
  18. 麻球繁衍(Tribbles 概率dp)
  19. Python电子相册
  20. 软件测试周刊(第43期):如果你过普通生活过了很久,只要你稍微努点力,你就以为拼尽了全力,其实不是的。

热门文章

  1. 我的编程之路——VB篇
  2. java 测试---案例实现
  3. jquery进度条_jQuery进度栏
  4. 计算机硬盘驱动器可以存软件吗,如何从计算机硬盘驱动器恢复数据
  5. 关于Y400 电源管理 Win10解决方案
  6. 《赛灵思中国通讯》学习记录第1期:为何使用Zynq SoC可以让企业产品利润激增
  7. matlab 电力电子仿真电路,基于Matlab的电力电子电路仿真方法
  8. 华为手机应用程序变为Android图标,华为手机如何改变应用图标
  9. C语言_写简易吃豆人小游戏
  10. 日本专利如何检索 昭57-192247