设计模式 代理模式(静态代理 动态代理) 与 Spring Aop源码分析 具体是如何创建Aop代理的

代理模式

代理模式是一种结构型设计模式,它通过创建一个代理对象来控制对真实对象的访问。这种模式可以用于提供额外的功能操作,或者扩展目标对象的功能。

在代理模式中,代理对象与真实对象实现相同的接口,以便在任何地方都可以使用相同的接口来调用真实对象的方法。这样做的好处是可以在不改变原始代码的情况下,增加或修改代码的行为。

根据创建代理对象的方式和时机,代理模式可以被分为静态代理、动态代理等类型。其中,静态代理是由程序员在编译时期就定义好的代理类,而动态代理则是在程序运行时期通过Java反射机制动态生成的。

在实际生活中,有许多应用了代理模式的场景,例如租房、卖房、家政等业务,通常由中介机构作为代理来进行操作。

静态代理

静态代理在编译期间就已经确定代理类的代码。具体来说,要实现静态代理需要手动编写代理类的代码,因此这种方式的灵活性相对较差,但由于代理类是直接编写的,所以其运行效率较高。

首先定义购房者的行为

/*** 购房者** @author LionLi*/
public interface Homebuyer {/*** 需求*/String need();/*** 购买*/void buy();
}

定义真实购房者

/*** 购房者 张三** @author LionLi*/
public class Zhangsan implements Homebuyer {/*** 需求*/@Overridepublic String need() {String need = "100平以上三室两厅两卫";System.out.println("张三: " + need);return need;}/*** 购买*/@Overridepublic void buy() {System.out.println("张三: 我已付款");}
}
/*** 购房者 王五** @author LionLi*/
public class Wangwu implements Homebuyer {/*** 需求*/@Overridepublic String need() {String need = "70平左右两室一厅";System.out.println("王五: " + need);return need;}/*** 购买*/@Overridepublic void buy() {System.out.println("张三: 我已付款");}
}

定义房产中介

/*** 房产中介代理人** @author LionLi*/
public class HouseAgentProxy implements Homebuyer {private Homebuyer homebuyer;public HouseAgentProxy(Homebuyer homebuyer) {this.homebuyer = homebuyer;}@Overridepublic String need() {System.out.println("中介: 你对房子有什么需求 放心交给我");String need = homebuyer.need();System.out.println("中介: 寻找房源中........");System.out.println("中介: 寻找房源中........");System.out.println("中介: 寻找房源中........");String str = "中介: 为您找到" + need + "的房子";System.out.println(str);return str;}@Overridepublic void buy() {System.out.println("中介: 请支付购买房子");homebuyer.buy();System.out.println("中介: 合同生效中.....");System.out.println("中介: 房证办理中.....");System.out.println("中介: 恭喜您 这套房子属于您了");}
}

测试

/*** @author LionLi*/
public class Test {public static void main(String[] args) {Homebuyer zhangsan = new Zhangsan();HouseAgentProxy agent1 = new HouseAgentProxy(zhangsan);agent1.need();agent1.buy();System.out.println("-----------------------------");Homebuyer wangwu = new Wangwu();HouseAgentProxy agent2 = new HouseAgentProxy(wangwu);agent2.need();agent2.buy();}
}

两位购房者分别根据需求在中介的带领下买到了房子 真是可喜可贺啊

动态代理

动态代理允许在运行时动态地创建代理对象。代理对象可以在调用实际对象的方法前后执行一些额外的操作,比如日志记录、权限检查等。

动态代理的实现方式有两种:基于接口和基于继承。基于接口的方式是最常用的,它使用Java的反射机制来实现代理对象。基于继承的方式则需要创建一个实现了目标类接口的子类,并重写其中的方法。

优点: 可以降低系统的耦合度,提高代码的可维护性和可扩展性。
缺点: 需要使用反射机制,性能比静态代理略低。

首先定义购房者的行为与实际购房者

使用上方代码不变

定义房产中介

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 动态房产中介代理人** @author LionLi*/
public class DynamicHouseAgentProxy implements InvocationHandler {private Homebuyer homebuyer;public Homebuyer getInstance(Homebuyer homebuyer) {this.homebuyer = homebuyer;return (Homebuyer) Proxy.newProxyInstance(homebuyer.getClass().getClassLoader(), homebuyer.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("need")) {System.out.println("中介: 你对房子有什么需求 放心交给我");String need = (String) method.invoke(homebuyer, args);System.out.println("中介: 寻找房源中........");System.out.println("中介: 寻找房源中........");System.out.println("中介: 寻找房源中........");String str = "中介: 为您找到" + need + "的房子";System.out.println(str);return str;} else if (method.getName().equals("buy")) {System.out.println("中介: 请支付购买房子");Object invoke = method.invoke(homebuyer, args);System.out.println("中介: 合同生效中.....");System.out.println("中介: 房证办理中.....");System.out.println("中介: 恭喜您 这套房子属于您了");return invoke;}return null;}
}

测试

/*** @author LionLi*/
public class Test {public static void main(String[] args) {DynamicHouseAgentProxy agent = new DynamicHouseAgentProxy();Homebuyer zhangsan = new Zhangsan();Homebuyer proxy1 = agent.getInstance(zhangsan);proxy1.need();proxy1.buy();System.out.println("-----------------------------");Homebuyer wangwu = new Wangwu();Homebuyer proxy2 = agent.getInstance(wangwu);proxy2.need();proxy2.buy();}}


结果不变 两位购房者成功买到房子

Cglib动态代理

其他代码不变只变更中介类

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** 动态房产中介代理人** 这里由于cglib已经不支持jdk17了 所以我们使用spring内部自带的cglib工具** @author LionLi*/
public class DynamicHouseAgentProxy implements MethodInterceptor {public Homebuyer getInstance(Homebuyer homebuyer) {Enhancer enhancer = new Enhancer();// 设置继承父类enhancer.setSuperclass(homebuyer.getClass());// 设置回调enhancer.setCallback(this);return (Homebuyer) enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {if (method.getName().equals("need")) {System.out.println("中介: 你对房子有什么需求 放心交给我");String need = (String) proxy.invokeSuper(obj, args);System.out.println("中介: 寻找房源中........");System.out.println("中介: 寻找房源中........");System.out.println("中介: 寻找房源中........");String str = "中介: 为您找到" + need + "的房子";System.out.println(str);return str;} else if (method.getName().equals("buy")) {System.out.println("中介: 请支付购买房子");Object invoke = proxy.invokeSuper(obj, args);System.out.println("中介: 合同生效中.....");System.out.println("中介: 房证办理中.....");System.out.println("中介: 恭喜您 这套房子属于您了");return invoke;}return null;}
}

Spring中代理模式的应用

要说起Spring中的代理模式 要首当其冲的肯定是AOP了 接下来我们来看看在AOP中是如何使用代理模式的

这里涉及到一个注解 学过AOP的都知道 如果需要开启AOP那么需要增加这个注解

通过搜索找到 AspectJAutoProxyRegistrar 类, 该方法的作用就是往Spring容器中添加一个 BeanDefinition 类型为 AnnotationAwareAspectJAutoProxyCreator 用于创建代理对象


接下来我们进入 AnnotationAwareAspectJAutoProxyCreator 看看是如何创建代理的

由于 AnnotationAwareAspectJAutoProxyCreator 中并没有创建代理的方法 那么我们只能向上去父类里找, 通过不断的探索在 AnnotationAwareAspectJAutoProxyCreator -> AspectJAwareAdvisorAutoProxyCreator -> AbstractAdvisorAutoProxyCreator -> AbstractAutoProxyCreator 抽象类 AbstractAutoProxyCreator 中找到了 createProxy 方法


此方法是bean初始化的前置处理器 postProcessBeforeInstantiation 中使用的, 也就是说bean在初始化之前, 代理对象就已经创建好了

进入 createProxy 方法

进入 buildProxy 方法


这里我们可以看出 实际的代理对象是通过 ProxyFactory 工厂的 getProxyClassgetProxy 两个方法创建的

我们来看一下这两个方法具体实现

通过 getProxyClass 方法一直往下点 找到最终创建方法 DefaultAopProxyFactory#createAopProxy 为止


最后我们来分析最终是如何创建代理对象的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/410288.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

诊断试剂市场调研:预计2029年将达到859亿美元

诊断试剂从一般用途来分,可分为体内诊断试剂和体外诊断试剂两大类。除用于诊断的如旧结核菌素、布氏菌素、锡克氏毒素等皮内用的体内诊断试剂等外,大部分为体外诊断制品。 诊断试剂可分为体内诊断试剂和体外诊断试剂两大类。从近年来的诊断试剂产品结…

Hive数据定义(2)

hive数据定义是hive的基础知识,所包含的知识点有:数据仓库的创建、数据仓库的查询、数据仓库的修改、数据仓库的删除、表的创建、表的删除、内部表、外部表、分区表、桶表、表的修改、视图。在上一篇文章中介绍了一部分知识点,在本篇文章中将…

2024中国光伏展

2024年中国光伏展预计将是一个规模庞大的展览,吸引了全球光伏行业的专业人士和企业参与。光伏展将为各个光伏领域的企业提供一个展示最新技术、产品和解决方案的平台。 在2024年的中国光伏展上,参展企业将能够展示他们的光伏组件、太阳能电池板、逆变器、…

鸿蒙Harmony-列表组件(List)详解

不要和别人比生活,每个人阶段不同,追求不同,活法自然也不同。只要今天的你能比昨天的你快乐一点点,那你就是自己人生赢家。 目录 一,定义 二,布局与约束 2.1 布局 2.2 约束 三,开发布局 3.1 设置…

三、Qt Creator 使用

关于Qt的安装及环境配置,在我的上一篇《二、QT下载、安装及问题解决(windows系统)》已经讲过了。 本章节有一个重点,在新建 工程文件时,所在路径不要有中文,否则编译及运行程序不能正常运行。 在使用Qt Creator(以下…

Python 布尔类型:了解真假之间的探索

Python 是一种备受欢迎的编程语言,以其简洁、灵活和易学易用而闻名。其中一个重要的数据类型就是布尔类型(bool),它代表了逻辑上的真(True)和假(False)。在 Python 中,布…

【数据库】聊聊MVCC机制与BufferPool缓存机制

上一篇文章,介绍了隔离级别,MySQL默认是使用可重复读,但是在可重复读的级别下,可能会出现幻读,也就是读取到另一个session添加的数据,那么除了配合使用间隙锁的方式,还使用了MVCC机制解决&#…

【算法分析与设计】跳跃游戏

题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到达 nums[n - …

vue中使用mpegts.js播放flv的直播视频流

第一步&#xff1a;引入mpegts.js npm install --save mpegts.js 第二步&#xff1a;在vue文件中引入mpegts.js的依赖 第三步&#xff1a;编写展示视频的盒子 我这里是使用循环遍历的方式创建video标签&#xff0c;这样方便后面随机展示视频使用 <template><div>&l…

甄选7款前端动画特效源码资源分享(附在线预览)

分享7款有趣也实用的前端动画特效 其中有CSS动画、canvas动画、js小游戏等等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 交互式加载动画 基于three.js制作的一款交互式加载动画 鼠标长按时还有环形的过渡到圆圈的效果…

第十二章 Java内存模型与线程(二)

文章目录 12.4 Java与线程12.4.1 线程的实现12.4.2 Java线程调度12.4.3 状态转换 12.5 Java与协程12.5.1 内核线程的局限12.5.2 协程的复苏12.5.3 Java的解决方案 12.4 Java与线程 12.4.1 线程的实现 实现线程主要有三种方式&#xff1a;使用内核线程实现&#xff08;1&#…

LLaMa2 Chat gpt 大模型本地部署初体验

一直想在自己电脑或者测试环境随便找台服务器尝试部署一下“大模型”&#xff0c;但“大模型”对于内存和GPU的要求令人望而却步&#xff0c;层出不穷的各种术语也令人困惑&#xff0c;有点难以下手。 经过一段时间&#xff0c;在百度千帆大模型平台、讯飞星火大模型平台、魔搭…