前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring系列七:JDK 动态代理和 CGLIB 代理

Spring系列七:JDK 动态代理和 CGLIB 代理

原创
作者头像
叶秋学长
发布2022-07-27 21:00:47
3050
发布2022-07-27 21:00:47
举报
文章被收录于专栏:全栈学习专栏全栈学习专栏

JDK相信小伙伴们对它十分熟悉,那么小伙伴们知道JDK动态代理和CGLIB代理的区别吗?接下来由叶秋学长带领小伙伴对它们进行深入学习吧~~

21.说说JDK 动态代理和 CGLIB 代理 ?

Spring的AOP是通过动态代理来实现的,动态代理主要有两种方式JDK动态代理和Cglib动态代理,这两种动态代理的使用和原理有些不同。

JDK 动态代理

  1. Interface:对于 JDK 动态代理,目标类需要实现一个Interface。
  2. InvocationHandler:InvocationHandler是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在次过程,可能包装逻辑,对目标方法进行前置后置处理。
  3. Proxy:Proxy利用InvocationHandler动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。

CgLib 动态代理

  1. 使用JDK创建代理有一大限制,它只能为接口创建代理实例,而CgLib 动态代理就没有这个限制。
  2. CgLib 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
  3. CgLib 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

我们来看一个常见的小场景,客服中转,解决用户问题:

编辑

用户向客服提问题

JDK动态代理实现:

编辑

JDK动态代理类图

  • 接口 public interface ISolver { void solve(); }
  • 目标类:需要实现对应接口 public class Solver implements ISolver { @Override public void solve() { System.out.println("疯狂掉头发解决问题……"); } }
  • 态代理工厂:ProxyFactory,直接用反射方式生成一个目标对象的代理对象,这里用了一个匿名内部类方式重写InvocationHandler方法,实现接口重写也差不多 public class ProxyFactory { // 维护一个目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } // 为目标对象生成代理对象 public Object getProxyInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("请问有什么可以帮到您?"); // 调用目标对象方法 Object returnValue = method.invoke(target, args); System.out.println("问题已经解决啦!"); return null; } }); } }
  • 客户端:Client,生成一个代理对象实例,通过代理对象调用目标对象方法 public class Client { public static void main(String[] args) { //目标对象:程序员 ISolver developer = new Solver(); //代理:客服小姐姐 ISolver csProxy = (ISolver) new ProxyFactory(developer).getProxyInstance(); //目标方法:解决问题 csProxy.solve(); } }

Cglib动态代理实现:

编辑

Cglib动态代理类图

  • 目标类:Solver,这里目标类不用再实现接口。 public class Solver { public void solve() { System.out.println("疯狂掉头发解决问题……"); } }
  • 动态代理工厂: public class ProxyFactory implements MethodInterceptor { //维护一个目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } //为目标对象生成代理对象 public Object getProxyInstance() { //工具类 Enhancer en = new Enhancer(); //设置父类 en.setSuperclass(target.getClass()); //设置回调函数 en.setCallback(this); //创建子类对象代理 return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("请问有什么可以帮到您?"); // 执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("问题已经解决啦!"); return null; } }
  • 客户端:Client public class Client { public static void main(String[] args) { //目标对象:程序员 Solver developer = new Solver(); //代理:客服小姐姐 Solver csProxy = (Solver) new ProxyFactory(developer).getProxyInstance(); //目标方法:解决问题 csProxy.solve(); } }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 21.说说JDK 动态代理和 CGLIB 代理 ?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档