看了这篇文章,你会对静态代理模式,JDK 动态代理模式和 CGLIB 动态代理模式有个很清晰的认识。

01、简介

  1. 什么是代理模式

    代理模式也称为委托模式,属于结构型模式之一。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用,比如我们生活中的邮局,快递公司,婚介所等等。

  2. 代理模式分类

    代理模式分为静态代理模式和动态代理模式。

    静态代理是由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行之前,代理类.class文件就已经被创建了

    动态代理是在程序运行时通过java反射机制动态创建的。

  3. 代理模式的目的

    代理模式主要有两个目的:一保护目标对象,二增强目标对象。

02、静态代理模式

静态代理模式的话我模拟一个古代结婚的场景。场景是这样的:在古代,某家的公子看上了别家的姑娘,一般都是家里的大人去姑娘的家里提亲,双方父母同意了,然后就拜堂成婚,后面要宴请亲朋好友。这里这个公子只需要拜堂成婚就行了,至于提亲和宴请亲友都是父母操办的。我们用代码来模拟一下这个场景。

首先我们来建个 Person 接口:

public interface Person {/*** 人有很对行为,这里我们用到的是结婚*/void marry();
}

然后这家公子要成亲,我们建个 Son 类实现 Person 接口:

public class Son implements Person {@Overridepublic void marry() {System.out.println("我终于结婚了");}
}

父亲帮儿子提亲,建个 Father 类:

public class Father {private Son son;public Father(Son son){this.son = son;}public void marry(){System.out.println("父亲上门提亲");this.son.marry();System.out.println("父亲宴请亲友");}
}

最后是测试代码:

public class Test {public static void main(String[] args) {Father father = new Father(new Son());father.marry();}
}

输出:

父亲上门提亲
我终于结婚了
父亲宴请亲友

代码写完了,大家有没有发现静态代理模式的一个缺点。那就是单一,一个类只能代理一个目标对象。比如上面的场景,父亲只能为自己的儿子提亲,不能为别人家的孩子提亲。

下面我们来看看动态代理是怎么解决这个问题的。

03、动态代理模式

动态代理模式分为 JDK 动态代理和 cglib 动态代理两种。这里先用 JDK 动态代理的方式来模拟一个通过婚介所找朋友的场景。

先将 Person 接口改动下:

public interface Person {/*** 找朋友*/void findFriend();
}

然后是婚介所 JDKMatrimonialAgency 类:

public class JDKMatrimonialAgency implements InvocationHandler {//被代理的对象,把引用给保存下来private Object target;public Object getInstance(Object target) throws Exception{this.target = target;Class<?> clazz = target.getClass();return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object obj = method.invoke(this.target,args);after();return obj;}private void before(){System.out.println("这里是婚介所,请提供你的需求");}private void after(){System.out.println("已经找到合适的,尽快安排你相亲");}
}

JDK 动态代理主要是实现 InvocationHandler 接口,并实现 invoke 方法

然后创建 Customer 类:

public class Customer implements Person {@Overridepublic void findFriend() {System.out.println("我要找一个胸大,腿长又好看的美女");}
}

最后测试类:

public class Test {public static void main(String[] args) {try {Person obj = (Person)new JDKMatrimonialAgency().getInstance(new Customer());obj.findFriend();} catch (Exception e) {e.printStackTrace();}}
}

看下结果:

这里是婚介所,请提供你的需求
我要找一个胸大,腿长又好看的美女
已经找到合适的,尽快安排你相亲

然后我们用 CGLIB 来实现,如果不是spring(spring已经集成了 CGLIB )环境需要先引入 jar 包:

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

然后加一个 CglibMatrimonialAgency 类:

public class CglibMatrimonialAgency implements MethodInterceptor {public Object getInstance(Class<?> clazz) throws Exception{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 {//业务的增强before();Object obj = methodProxy.invokeSuper(o,objects);after();return obj;}private void before(){System.out.println("这里是婚介所,请提供你的需求");}private void after(){System.out.println("已经找到合适的,尽快安排你相亲");}
}

CGLIB 主要是实现 MethodInterceptor 并实现 intercept 方法。

看下结果:

这里是婚介所,请提供你的需求
我要找一个胸大,腿长又好看的美女
已经找到合适的,尽快安排你相亲

04、JDK和CGLIB动态代理对比

  1. JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。

  2. JDKCGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。

  3. JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法,CGLib 执行效率更高。

05、代理模式的优缺点

优点:

  1. 降低耦合度,扩展性好

  2. 代理对象将代理对象和目标对象分离,起到保护目标对象的作用

  3. 可以对目标对象的功能增强

缺点:

  1. 增加类的数量

  2. 因为会调用增强方法,所以会造成处理速度慢

  3. 增加了系统的复杂度(这是好的架构都会有的缺点,比如spring)

近期热文

  • 面试珍藏:最常见的200多道Java面试题

  • 被一个熟悉的面试题问懵了:String...

  • 面试官:如何实现幂等性校验?

【END】

关注下方二维码,订阅更多精彩内容

朕已阅 

面试官 | 说一下什么是代理模式?相关推荐

  1. 面试官:什么是静态代理?什么是动态代理?注解、反射你会吗?

    前言 开场 一位穿着蓝色衬衫,牛仔裤,拿着一个白色保温杯的中年男子急匆匆地坐在你对面,看样子是项目上的东西很急,估摸面试时间不会太长,这样一想心情放松了许多-(后来我就被打脸了) ​ ​ 面试开始 面 ...

  2. 面试官都爱问的java模式之装饰模式!!!

    简言: Java中的23种设计模式: Factory(工厂模式),Singleton(单例模式),Adapter(适配器模式),FactoryMethod(工厂方法模式),Prototype(原始模型 ...

  3. 抽象工厂模式java_面试官:说一下静态工厂模式,工厂方法模式,抽象工厂的区别吧...

    静态工厂模式 用生活中的场景类比一下这三种模式,假如你想学习Java视频,你得自己到处去找资料,找资料是一个繁琐的过程,过一段时间你又想学Python视频了,你还得去找资料.现在你在学校上学,你想学J ...

  4. 面试官:什么是责任链模式?

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 最近在看项目代码的时候发现「责任链模式」,于是想 ...

  5. 面试官都爱问的java模式之建造者模式!!!

    开心一刻: 同事妻管严,零花钱少的可怜,今天一起打牌他输了400块没钱了.想想也可怜,就请他吃饭,吃饭时他说兄弟借十块钱吧,买张请柬回去好报帐,我当时就呆了,又TM学会一招... 简言: 建造者模式定 ...

  6. 【运维面试】面试官:LVS都有哪些模式,你们公司用的哪一种?

    文章目录 1. NAT模式 2. DR模式 3. 其他模式 4. 四种模式的性能比较 回答范例 1. NAT模式 故事版: 王小虎是谍报活动的特工人员,这天傍晚他一身黑衣,来到一个当铺,溜达了一圈后, ...

  7. 面试官:建造者模式是什么?

    宝剑锋从磨砺出.梅花香自苦寒来 文章持续更新,可以微信搜索[小奇JAVA面试]第一时间阅读,回复[资料]更有我为大家准备的福利哟!回复[项目]有我为大家准备的一些项目源码.回复[简历模板]有我为大家准 ...

  8. 面试官问:代理模式和装饰者模式有啥区别

    今天面试聊到了模式. 面试官问:装饰者模式了解吗,讲一下? 我:blabla... 面试官:那代理模式呢? 我:blabla.....(说完感觉怎么都一样呢) 果然,面试官又问了:那两者有什么区别呢? ...

  9. 面试官:策略模式和代理模式有什么区别?

    大家好,我是田哥,昨天一哥们面试被问到代理模式,刚好,我也正在写<MyBatis源码分析:小白系列>专栏中的代理模式. 这里也说明一下,本文是MyBatis源码分析专栏中的一篇文章. 感兴 ...

最新文章

  1. #人生中对我最重要的三位老师
  2. vue 2个方法先后执行_演讲你早该知道的2个演讲方法
  3. Linux常用命令简述--wc
  4. 算法(11)-leetcode-explore-learn-数据结构-链表的经典问题
  5. 来自顶级名校推荐的英文书单,留着慢慢啃!
  6. 一男子安装lua开发环境傻逼操作,惊呆所有人
  7. vue项目调用jssip_JsSIP和FreeSWITCH整合
  8. Win10下启动telnet客户端
  9. 另一个进程已被死锁在资源上且该事务已被选作死锁牺牲品
  10. 关于生活工作学习之感悟-第一篇
  11. React Component Lifecycle(生命周期)
  12. Centos7 安装zmap
  13. 环绕声混响效果器-Acon Digital Verberate Immersive 2.2.1 WiN-MAC
  14. qemu-nbd挂载虚拟机镜像文件系统
  15. 多linux系统u盘制作,高手教你如何做一个U盘Linux系统
  16. 各种常用电子元器件的识别方法
  17. 3DGIS地理信息系统设计方案
  18. python 爬虫 运用urlopen() 和urlretrieve()方法傻瓜操作 爬取虎牙直播主播头像
  19. 基于Apache Curator框架的ZooKeeper基本用法详解
  20. 电脑文件如何传到云服务器上,电脑文件如何传到云服务器上

热门文章

  1. html图片热点新窗口,HTML基础必看---表单,图片热点,网页划区和拼接详解
  2. 【SpringBoot 2】(三)SpringBoot相较于Spring的特点
  3. 19-数据持久化-Bind Mounting
  4. apache ab压力测试报错
  5. 深度学习在搜索业务中的探索与实践 1
  6. springboot系列(十)springboot整合shiro实现登录认证
  7. Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。
  8. windows进入mysql
  9. JAVA调用动态链接库
  10. C#中split分隔字符串的应用