Spring中静态代理与动态代理的区别

前言

代理模式在Java中特别常见,如spring AOP功能就是用代理来实现的。代理模式作用是:在不修改被代理对象功能的基础上,通过对代理类进行扩展,进行一些功能上的附加与增强。
一般使用代理模式我们需要先定义一个接口,静态代理只是一种简单的java代码功能扩展。而动态代理利用了反射机制,使用更简单。

无论是静态代理还是动态代理,都有四大角色:

  1. 抽象角色:一般会使用接口或者抽象类来解决
  2. 真实角色:被代理的角色
  3. 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
  4. 客户:访问代理对象的人

静态代理(中介租房案例)

首先,定义一个接口(Rent),房东类(Host)实现该接口,并输出自己房子的相关信息。

//租房
public interface Rent {public  void rent();
}
//房东
public class Host implements Rent{public void rent() {System.out.println("我的房子是蓝色的,准备出租房子!");}
}

房东将房子交给中介,此时的中介相当于代理类,故创建代理类(Proxy),代理类在不修改被代理对象功能的基础上(Host类的rent方法),可以对代理类进行扩展,进行一些功能上的附加与增强(增加seeHouse、hetong、fare方法)。

public class Proxy implements Rent{private Host host;public Proxy(){ }public Proxy(Host host){this.host=host;}public void rent() {seeHouse();host.rent();hetong();fare();}//看房public void seeHouse(){System.out.println("中介带你看房子");}//签合同public void hetong(){System.out.println("签合同");}
//    收费public void fare(){System.out.println("收中介费");}
}

客户购房不用面对房东,只需与中介对接。

public class Client {public static void main(String[] args) {Host host=new Host(); //房东要出租房子//代理,中介帮房东租房子,但是代理角色一般会有一些附属操作Proxy proxy=new Proxy(host);//客户不用面对房东,直接找中介租房即可proxy.rent();}
}

上述代码就实现了静态代理,客户只需面向代理类操作即可。

运行截图:

静态代理的优点:

  1. 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
  2. 公共也就交给代理角色,实现了业务的分工
  3. 业务发生扩展的时候,方便集中管理

静态代理的缺点:

  1. 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率变低。

动态代理

静态代理中,每个真实对象都会拥有一个代理类,这样将会十分繁琐,采用动态代理将会解决这种问题!我们在上述的中介租房案例中进行修改。

首先创建一个Rent接口,并创建两个房东类实现Rent接口。

//租房
public interface Rent {public  void rent();
}
//房东1
public class Host implements Rent {public void rent() {System.out.println("我的房子是蓝色的,准备出租房子!");}
}
//别的房东
public class Host_other implements Rent{public void rent() {System.out.println("我的房子是红色的,准备出租房子!");}
}

如果采用静态代理,我们将要编写两个代理类,当房东数量很大时,这种处理方法明显不妥,因此我们可以编写一个代理工具类,该类并未指明代理的真实对象是哪一个,相当于我们之前学Java时编写的Math类(完成某种特定的计算过程)。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//我们会用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {//被代理的接口private Object target;public void setTarget(Object target){this.target=target;}//生成得到代理类public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}//处理代理实例,并返回结果public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//动态代理的本质,就是使用反射机制实现seeHouse();Object result=method.invoke(target,args);fare();return result;}public void seeHouse(){System.out.println("中介带你看房子");}public void fare(){System.out.println("收中介费");}
}

其中的target变量,就是未来客户类传入的真实对象。很明显,动态代理也能在不改变原有业务代码的基础上,实现对功能的扩展(seeHouse等方法的加入)。

在客户类中,只需new多个代理工具类,并为他们传入相应的真实对象,就可以获取各个真实对象的rent方法。

public class Client {public static void main(String[] args) {//真实角色Host host=new Host();//代理角色:现在没有ProxyInvocationHandler pih=new ProxyInvocationHandler();//通过调用程序处理角色来处理我们要调用的接口对象!pih.setTarget(host);Rent proxy=(Rent)pih.getProxy();//这里的proxy就是动态生成的,我们并没有写这个类proxy.rent();System.out.println("--------------------------");//真实角色Host_other host_other=new Host_other();//代理角色:现在没有ProxyInvocationHandler pih1=new ProxyInvocationHandler();//通过调用程序处理角色来处理我们要调用的接口对象!pih1.setTarget(host_other);Rent proxy1=(Rent)pih1.getProxy();//这里的proxy1就是动态生成的,我们并没有写这个类proxy1.rent();}
}

运行结果见下图:

动态代理的好处:

  1. 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
  2. 公共业务就交给代理角色,实现了业务分工
  3. 公共业务发生扩展的时候,方便集中管理
  4. 一个动态代理类代理的是一个接口,一般就是对应的一类业务(多个类实现同一个接口,只要重写方法,客户端可以通过修改代理的真实对象来实现动态的代理)
  5. 多个房东同时卖房,他们的房子信息不一样,如果采用静态代理,需要为他们各自写一个代理类,就十分麻烦。我们可以采用动态代理的方法,让这些房东同时实现一个接口(Rent),这样我们在客户类只需要修改代理的真实对象,就可以得到每个房东各自的房子信息。

总结

无论是静态代理还是动态代理,都符合下面几个步骤:

  1. 创建接口
  2. 创建真实角色并实现接口
  3. 创建代理类
  4. 客户类访问代理角色

不同的是静态代理需要为每个真实对象创建一个代理类,而动态代理只用为同一类业务创建一个代理工具类即可。

Spring中静态代理与动态代理的实现及区别相关推荐

  1. Linux中静态库和动态库(共享库)的区别

    1. 静态库和动态库的制作过程区别 1.1 静态库的制作过程 详见博客:Linux中静态库的制作与使用 1.2 动态库的制作过程 详见博客:Linux中动态库(共享库)的制作与使用 2. 静态库和动态 ...

  2. web中静态资源和动态资源的概念及区别

    1.静态资源和动态资源的概念 简单来说: 静态资源:一般客户端发送请求到web服务器,web服务器从内存在取到相应的文件,返回给客户端,客户端解析并渲染显示出来. 动态资源:一般客户端请求的动态资源, ...

  3. Spring AOP中的静态代理和动态代理的原理和实践

    对于最近博主最近写博客的兴致大发,我也在思考:为什么而写博客?在互联网时代,无论你是牛人大咖,还是小白菜鸟,都有发表自己看法的权利.无论你是对的还是错的,都会在这个平台上找到答案.所以,我会尽可能去写 ...

  4. Spring中的静态代理和动态代理

    一.什么是代理? 代理是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象.可以不修改目标对象,对目标对象功能进行拓展.在我们学习Spring的时候就会发现,AOP(面向切面编程 ...

  5. Spring系列之静态代理、动态代理、cglib代理与Spring AOP的处理

    本章内容 代理的概念及理解 如何实现静态代理 如何实现动态代理 静态代理与动态代理有什么区别与优缺点 JDK动态代理如何实现 cglib动态代理如何实现 JDK动态代理与cglib动态代理的区别 Sp ...

  6. AOP的实现原理 —— 静态代理 和 动态代理( Spring AOP)

    文章目录 一.AOP是什么? 二.静态代理 -- AspectJ 2.1.举例说明 三. 动态代理 3.1.JDK 动态代理 3.1.1. 核心类: 3.1.2. 示例1--JDK动态代理 3.2.C ...

  7. Spring——AOP学习(静态代理和动态代理模式)

    Spring--AOP学习(静态代理和动态代理模式) 一.代理模式 我们知道学习Spring最重要的两个知识点就是IOC和AOP,AOP的主要思想就是动态代理模式.在了解AOP之前我们必须学习动态代理 ...

  8. Spring的静态代理和动态代理

    2019独角兽企业重金招聘Python工程师标准>>> 代理模式主要有两种:静态代理和动态代理 1,静态代理: 比如要在输出"HelloWorld"前打印一个字符 ...

  9. Spring BPP中优雅的创建动态代理Bean

    Spring BPP中优雅的创建动态代理Bean 一.前言 本文章所讲并没有基于Aspectj,而是直接通过Cglib以及ProxyFactoryBean去创建代理Bean.通过下面的例子,可以看出C ...

  10. 一篇文章让你搞懂Java中的静态代理和动态代理

    文章目录 什么是代理模式 代理的优缺点 静态代理 动态代理 InvocationHandler 接口 和 invoke 方法介绍 静态代理和动态代理的区别 什么是代理模式 代理模式是常用的java设计 ...

最新文章

  1. 黑科技揭秘 | 阿里云“天空物联网”连接范围如何达到700平方公里
  2. linux shell 杀进程 kill 包含关键字的进程
  3. python论坛哪些好-好的python论坛
  4. python常用内置函数总结-python常见的内置函数
  5. Linux命令——cp
  6. 《面向对象程序设计》第07章在线测试
  7. 对话中国经济和信息化-万祥军:李玉庭制造企业重整电商
  8. 看门狗寄存器c语言代码_「正点原子NANO STM32F103开发板资料连载」第十一章 看门狗实验...
  9. node中的js-核心模块
  10. 数据库设计笔记——有效设计数据库的目标(二)
  11. pdo mysql_PDO MySQL
  12. python3默认编码标准是_python3 编码
  13. 转化关系模型外键_网站数据分析:流量运营分析模型拯救你的广告流量
  14. linux环境下安装robot,install robotframework (linux)
  15. 固定 顶部_抗拉固定球铰支座优点与施工步骤
  16. SQL 标准发布第 15 部分:ISO/IEC 9075-15:2019 多维数组(SQL/MDA)
  17. 碳排放计算-20210515
  18. 衡量计算机储存容量的常用计量单位是,衡量存储器的单位是什么
  19. 传奇私服服务器移动玩家位置,传奇私服服务端里面哪个是玩家数据文件文件?...
  20. scad的oracle性质,变量选择之SCAD算法

热门文章

  1. [浅析]UE4关卡流
  2. python 做网站的工具_程序员最爱的网站克隆爬取工具- HTTrack
  3. meshlab点云转mesh
  4. 关于使用Curvy插件实现物体沿指定路径移动的方法
  5. 基于51单片机WiFi温湿度远程控制
  6. 老男孩python课程_老男孩python课程
  7. URL编码的原因及场景
  8. 【白话设计模式】23种设计模式一句话通俗讲解
  9. forge下载java_我的世界forge1.9.4
  10. Windows操作系统装机必备软件,值得收藏!