静态代理与动态代理(JDK、CGLIB)

问题引入

  • 什么是代理
  • 什么是静态代理?
  • 什么是动态代理?
  • 静态代理和动态代理的区别是什么?
  • JDK动态代理和CGLIB动态代理的区别?

代理

代理就是帮人做事情。比如我们现在很常用的代购场景,我媳妇需要买一套护肤品,去官网买的话比较贵,所以就找代购去买,代购其实也没有这个护肤品,但是他有渠道直接跟护肤品的商家有关系,能直接从商家拿这个护肤品,你是没办法联系上这个商家的,但是他肯定不能一点酬劳都不收,所以他会加价卖给你,这就是代理的典型模式。

静态代理

代理类是自己手动创建的,所需要代理的目标类是确定的,实现简单容易理解

例子

目标类:售卖兰蔻护肤品的商家

代理对象:拥有厂家拿货资格的代购

客户端:购买护肤品的用户

先创建目标类

/**
* 创建兰蔻买香水的接口类
**/
public interface LancomeSell {/*** 香水* @return*/BigDecimal perfume();
}
/*** Created on* 创建兰蔻厂家售卖香水实现类* @author*/
public class FactoryLancomeSellImpl implements LancomeSell {@Overridepublic BigDecimal perfume() {return new BigDecimal(120);}
}

在创建代理类:


/*** 通过厂家来拿到香水并且收取一定的费用** @author tengwang8* @version 1.0* @date 2022/3/25 18:01*/
public class DaiGouSell implements LancomeSell{FactoryLancomeSellImpl factoryLancomeSell = new FactoryLancomeSellImpl();@Overridepublic BigDecimal perfume() {BigDecimal factoryPerfume = factoryLancomeSell.perfume();return factoryPerfume.add(new BigDecimal(20));}
}

客户端(用户购买)

public class UserMain {public static void main(String[] args) {DaiGouSell daiGouSell = new DaiGouSell();System.out.println("daiGouSell.perfume(); = " + daiGouSell.perfume());}
}
优点:
  1. 在不修改目标类的情况下可以对目标类进行拦截和拓展。
  2. 实现简单
缺点:
  1. 当目标类增加了,代理类可能也需要成倍的增加
  2. 当你的接口中功能在增加了,或者修改了,会影响众多的实现类,厂家类,代理都需要修改,影响比较多.

动态代理

JDK动态代理
  1. 创建接口,定义目标类要完成的功能
  2. 创建目标类实现接口
  3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    1. 调用目标方法
    2. 增强功能
  4. 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型

目标类和接口实现同上面的静态代理,主要不同的地方是代理类的实现,代理类主要是通过反射,拿到目标类的接口的实现,来获取目标类对象,再目标类执行方法的时候进行拦截。

我们主要写一下实现Invocationhandler实现类

public class MyInvocationHandler implements InvocationHandler {Object target;//传入代理类MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Integer  result = 0;//调用目标方法Object res = method.invoke(target, args);if (res !=null ) {Integer price = (Integer) res;price = price +20;result =price;}return result;}
}

再看下我们的客户端调用

public class DynamicMain {public static void main(String[] args) {//实例化目标类FactoryLancomeSellImpl factoryLancomeSell = new FactoryLancomeSellImpl();//实例化Invocationhandler实现类MyInvocationHandler myInvocationHandler = new MyInvocationHandler(factoryLancomeSell);//创建代理类LancomeSell o = (LancomeSell) Proxy.newProxyInstance(factoryLancomeSell.getClass().getClassLoader(), factoryLancomeSell.getClass().getInterfaces(), myInvocationHandler);//调用目标方法  System.out.println("o = " +   o.perfume());}
}

还有第二种写法,就是在使用的时候再去实现InvocationHandler接口

  public static void main(String[] args) {FactoryLancomeSellImpl factoryLancomeSell = new FactoryLancomeSellImpl();
//        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(factoryLancomeSell);
//        LancomeSell o = (LancomeSell) Proxy.newProxyInstance(factoryLancomeSell.getClass().getClassLoader(), factoryLancomeSell.getClass().getInterfaces(), myInvocationHandler);
//        System.out.println("o = " +   o.perfume());LancomeSell o = (LancomeSell) Proxy.newProxyInstance(factoryLancomeSell.getClass().getClassLoader(), factoryLancomeSell.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Integer result = 0;Object res = method.invoke(factoryLancomeSell, args);if (res != null) {Integer price = (Integer) res;price = price + 20;result = price;}return result;}});Integer perfume = o.perfume();System.out.println("perfume = " + perfume);}
优点:

可以不用实现目标类的接口,直接通过反射拿到目标的方法进行拦截。

缺点:

目标类对象一定要实现接口

CGLIB代理

是通过字节码创建子类的方式,并在子类中采用方法拦截拦截父类所有的方法,进行切入。CGLIB可以代理没有接口的类。

先引入cglib包:

 compile group: 'cglib', name: 'cglib', version: '2.2.2'

目标类:

/*** Created on 2018/6/7* 没有接口的对象类* @author wang.teng*/
public class Business {public void execuate(){System.out.println("do something !");}
}

代理类:

/*** Created on 2018/6/7** @author wang.teng*/
public class CglibProxy implements MethodInterceptor {public Object getProxy(Class clazz){Enhancer enhancer = new Enhancer();enhancer.setSuperclass(clazz); //设置父类enhancer.setCallback(this);  //设置回调return enhancer.create();   //创建子类}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("前置交易");Object invokeSuper = methodProxy.invokeSuper(o, objects);System.out.println("后置交易");return invokeSuper;}
}
/*** Created on 2018/6/7** @author wang.teng*/
public class Test {public static void main(String[] args) {CglibProxy proxy = new CglibProxy();Business business = (Business) proxy.getProxy(Business.class);business.execuate();}}
优点:

可以代理类和接口,在执行效率比较高

缺点:

虽说在代理执行上效率比较高,但是在创建对象上,要使用字节码来进行创建对象,耗时会比JDK久很多。对于final修饰的方法是无法进行代理的。

总结

代理的理解(动态代理与静态代理)相关推荐

  1. 代理模式(Java版)-静态代理、JDK动态代理和CGLib动态代理

    代理模式前传 前几天有个小朋友问到我代理模式,这个我拿手的嘛.废话不多说,直接开讲?这是不可能的. 一般呢,讲模式之前呢,礼貌上都要讲个前传.象我这种老了根本不怕没有故事祭奠的人,随手一个前传开始. ...

  2. 静态代理,JDK动态代理和CGLIB代理入门学习

    之前面试时面试官问我:"你知道spring中有哪几种代理吗?" 啊?代理?啥子代理?VPN代理吗?嘿嘿,面试官你要种子直说啊......被刷下来了.好吧,入门学习下代理. 为什么需 ...

  3. 02.Java动态代理实现与原理分析之静态代理

    一.代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关 ...

  4. 动态代理:JDK动态代理和CGLIB代理的区别

    代理模式:代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的索引,实际执行时通过调用代理类的方法.实际执行的是被代理类的方法. 而AOP,是通过动态代理实现的. 一.简单来说: JD ...

  5. java代理学习(Proxy)之静态代理

    一.静态代理 总结: 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类 不足:静态代理实现了目 ...

  6. 23种设计模式之代理模式(动态代理)

    代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式的组成 抽 ...

  7. JAVA静态代理和动态代理理解

    这篇文章是,是我看到的将代理讲的即深入透彻又浅显易懂.转载自:https://blog.csdn.net/briblue/article/details/73928350 代理 代理是英文 Proxy ...

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

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

  9. Java代理模式/静态代理/动态代理

    代理模式:即Proxy Pattern,常用的设计模式之一.代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问. 代理概念 :为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委 ...

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

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

最新文章

  1. 综述的综述!5 篇2020 年「图像分割算法」最佳综述论文详解
  2. 在做mvc时遇到的一些问题
  3. linux 创建连接命令 ln -s 软连接
  4. JFace中的表格型树TableTreeViewer
  5. ICCV 2019 | Lifelong GAN:基于持续学习的条件图像生成模型
  6. 移除项目中的CocoaPods
  7. 机器学习常见数据集下载(免费)
  8. SEO搜索引擎优化 | hexo
  9. 也来说是 AngularJS、 Angular 2、Angular 4 的区别
  10. 包邮送30本Python技术书
  11. 【知识兔Excel教程】7个Excel序号填充的经典案例,照搬这些公式,效率倍增
  12. 基于SSM的婚纱影楼系统
  13. 解读中国版存款保险制度:差别费率+强监管色彩
  14. VC++中遇到的错误“Error spawning cl.exe”
  15. NGUI的动态字体dynamicFont的制作
  16. 地图的历史:从古代地图到 GIS
  17. 用 Flex Builder 3 + Pydev 打造全能 webgame 集成开发环境
  18. 小程序分销平台商城开发系统
  19. AOC V24t最薄24英寸
  20. python的循环控制结构_Python的控制结构之For、While、If循环问题

热门文章

  1. C\C++中getchar()函数
  2. 使用opencv的透视变换裁剪倾斜人脸
  3. Windwos2008如何关闭IE增强的安全配置
  4. 09-面向对象综合训练综合练习
  5. A商品69元,买二送一;即买3个商品,付2件钱,小于3件时,按原价购买。
  6. 什么样的企业算是负责任的企业
  7. 钕铁硼产品磁性能相对检测原理与技术
  8. Revit建模中 构件视图隐藏怎么操作?
  9. Android开发,登录注册界面中如何添加视频背景,亲测可用
  10. 【Vue.js】Vue 学习笔记