浅谈代理模式与java中的动态代理
代理模式的定义:
代理模式是一个使用律非常高的模式,定义如下:
为其他对象提供一种代理,以控制对这个对象的访问。
类图:
简单的静态代理:
public interface IRunner{
//这是一个代理类和被代理类都需要实现的接口
//在接口中定义一个抽象函数
public void request();
}
//下面是真实的被代理类
public class Runner implements IRunner{
//实现接口中的方法
public void request(){
//实现具体的业务逻辑
}
}
//下面是代理类
public class RunnerAgent implements IRunner{
//要代理哪个实现类
private IRunner runner = null;
//默认被代理者
public RunnerAgent(IRunner runner){
this.runner = runner;
}
//实现接口中定义的方法
public void request(){
this.before();
this.runner.request();
this.after();
}
//预处理
private void before(){
}
//后处理
private void after(){
}
}
- 我们可以看到静态代理只能代理某一个类,每个类都有一个代理类。在对通用性要求更高的场景下(比如Spring AOP)传统的静态代理不能满足需求,会使类的数目非常庞大,因此又有了动态代理。
动态代理
什么是动态代理?动态代理就是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。动态代理的一个重要应用就是面向切面编程(AOP)
AOP示意图:

通过示意图可以明显的看出来,AOP抽取出非业务逻辑代码,降低了耦合度。对于日志、事务、权限等都可以在系统设计阶段不用考虑,而在设计后通过AOP的方式织入。
动态代理的通用类图(jdk动态代理,如无特殊声明,以下动态代理均指jdk动态代理)

图中类和接口的代码:
//Subject接口
public interface Subject{
//业务操作
public void doSomething(String str);
}
//真实主题RealSubject类
public class RealSubject implements Subject{
//业务操作
public void doSomething(String str){
System.out.println("do something!--->" + str);
}
}
//动态代理的Handler类
public class MyInvocationHandler implements InvocationHandler{
//被代理对象
private Object target = null;
//构造函数
public MyInvocationHandler(Object _obj){
this.target = _obj;
}
//代理方法 覆盖接口InvocationHandler中的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable{
//执行被代理的方法
return method.invoke(this.target, args);
}
}
//动态代理类
public class DynamicProxy<T>{
public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) {
if(true) {
//执行一个前置通知
(new BeforeAdvice()).exec();
}
//执行目标函数
return (T) Proxy.newProxyInstance(loader, interfaces, h);
}
}
//通知接口及其实现
public interface IAdvice{
//通知方法
public void exec();
}
public class BeforeAdvice implements IAdvice{
public void exec(){
System.out.println("我是前置通知,我被执行了!");
}
}
//动态代理场景类
public class Client{
public static void main(String[] args){
//定义一个主题
Subject subject = new RealSubject();
//定义一个Handler
InvocationHandler handler = new MyInvocationHandler(subject);
//定义主题的代理
Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().
getClassLoader(), subject.getClass.getInterfaces(),handler);
//代理行为
proxy.doSomething("Finish");
}
}
运行结果:
我是前置通知,我被执行了!
do something!--->Finish
其中有这样的一行代码:return (T) Proxy.newProxyInstance(loader, interfaces, h);
这里使用interfaces指出了被代理对象实现的接口中的方法,因此jdk动态代理就要求被代理类必须实现接口。
h是接口InvocationHandler的实现类MyInvocationHandler的实例。由h对象的invoke方法负责接管被代理类实现的接口中的方法。
在运行时,只需通过subject.getClass.getInterfaces()传参,通过反射,达到了解耦的目的。
- jdk动态代理 vs cglib动态代理
jdk动态代理是以接口为中心的,相当于添加类一种对于被调用者没有太大意义的限制。我们实例化的是代理对象,而不是真正被调用的类型,这在实践中可能带来不便。
如果被调用者没有实现接口,而我们还是希望利用动态代理机制,那么可以考虑其他方式。我们知道Spring AOP支持两种模式的动态代理:jdk动态代理和cglib。如果我们选择cglib方式,就不再依赖接口。
cglib动态代理采取的方式是创建被代理类的子类。因此要求被代理类不可以用final修饰。
jdk动态代理的优势:
最小化依赖关系
代码实现简单。
cglib代理优势:
不需要被代理类实现额外接口。
只操作我们关心的类,而不必为其他相关类增加工作量。
高性能。
代理模式的优点
- 职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编程简洁清晰。 - 高扩展性
具体主题角色是随时都会发生变化的。只要实现了接口,不管如何变化,都离不开接口的规范,那我们的代理类完全就可以在不做任何修改的情况下使用。
参考文献:设计模式之禅 秦小波 著
浅谈代理模式与java中的动态代理的更多相关文章
- 代理模式与java中的动态代理
前言 代理模式又分为静态代理与动态代理,其中动态代理是Java各大框架中运用的最为广泛的一种模式之一,下面就用简单的例子来说明静态代理与动态代理. 场景 李雷是一个唱片公司的大老板,很忙, ...
- 10分钟了解 代理模式与java中的动态代理
前言 代理模式又分为静态代理与动态代理,其中动态代理是Java各大框架中运用的最为广泛的一种模式之一,下面就用简单的例子来说明静态代理与动态代理. 场景 李雷是一个唱片公司的大老板,很忙, ...
- 十分钟理解Java中的动态代理
十分钟理解 Java 中的动态代理 一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道 ...
- 深度剖析java中JDK动态代理机制
https://www.jb51.net/article/110342.htm 本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定 ...
- 一文读懂Java中的动态代理
从代理模式说起 回顾前文: 设计模式系列之代理模式(Proxy Pattern) 要读懂动态代理,应从代理模式说起.而实现代理模式,常见有下面两种实现: (1) 代理类关联目标对象,实现目标对象实现的 ...
- 使用Java中的动态代理实现数据库连接池
2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的 ...
- java中的动态代理机制
java中的动态代理机制 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现 ...
- Java 中的动态代理
一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者” ...
- Java中的动态代理(jdk和cglib)
JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类 ...
随机推荐
- 阿里P6晋升到P7是一个坎吗? P7 晋升总结
作者:程序之心丁仪 来源:https://chengxuzhixin.com/blog/post/P6_jin_sheng_dao_P7_zong_jie.html 公众号停更了挺长一段时间,首先说声 ...
- 「MCOI-03」村国题解
第二篇题解! 可能是退役之前的最后一篇题解了 (好像总共都只写了两篇) 不说了,讲题: 题面 题意: 有T个数据 有一颗树(保证所有的的节点都是相连的),有n个节点,每个节点都有相应的权值与序号,现在 ...
- MYSQL连接时错误码2059解决办法
一.问题原因: 如上图的报错提示可知,报错原因是caching_sha2_password不能加载. 这是因为8.0之后mysql更改了密码的加密规则,而目前已有的客户端连接软件还不支持Mysql8 ...
- SpringCloud gateway 过滤
如果需要获取一张图片但服务器没有过滤图片请求地址时,每次请求图片都需要携带token等安全验证密钥,可到nacos配置网关(gateway)的security配置,可过滤掉你配置的url(可理解为白名 ...
- Docker - 使用 Jenkins 镜像创建容器,并搭建 Python + Pytest +Allure 的自动化测试环境
如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 安装 Docker 直接参考我这 ...
- python08豆瓣电影 爬虫 BeautifulSoup + Reuqests
主要思路 请求豆瓣的链接获取网页源代码 然后使用 BeatifulSoup 拿到我们要的内容 最后就把数据存储到 excel 文件中
- python数据分析02语法基础
在我来看,没有必要为了数据分析而去精通Python.我鼓励你使用IPython shell和Jupyter试验示例代码,并学习不同类型.函数和方法的文档.虽然我已尽力让本书内容循序渐进,但读者偶尔仍会 ...
- Frontpage 三种回车键
Frontpage的回车键有三种:enter.shift+enter.ctrl+enter. enter键对应于HTML中的<p></p>,是一个段落的分界符. shift+e ...
- 什么是LRU缓存淘汰机制
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰.该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历 ...
- http代理阅读4 响应缓存处理
if (c->read->ready) { ngx_http_upstream_process_header(r, u); //读事件触发 准备处理http头部信息 return; } 向 ...