Spring中动态代理设计模式

目录

一、什么是动态代理

二、动态代理开发步骤

2.1 搭建开发环境

2.2 具体过程

三、动态字节码技术

四、动态代理开发简化代理开发


一、什么是动态代理

其实不管是静态代理还是动态代理其本质都是一样的,都是通过代理类为目标类增加额外功能,从而方便目标类的维护,只是在实现的过程中有所区别

二、动态代理开发步骤

2.1 搭建开发环境

在动态代理开发的过程中,是需要一些依赖的,将这些依赖文件导入pom.xml文件中

<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.1.14.RELEASE</version>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.8</version>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version>
</dependency>

2.2 具体过程

1)创建目标对象

在静态代理设计模式中,我们采取的是new对象的方式,这种方式是会产生耦合的,所以在动态代理的过程中使用Spring配置文件来创建对象

<bean id="userService" class="com.gl.demo.proxy.UserServiceImpl"/>

2)添加额外功能

创建好目标类之后我们需要去添加额外功能,这里添加额外功能就不再是自己定义一个类了,而是去实现Spring中的MethodBeforeAdvice接口。实现了这个接口就可以达成在目标类之前添加额外功能。然后再配置文件中创建出这个类的对象

public class Before implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {// 在则个方法中添加额外功能System.out.println("----method before advice log----");}
}
<bean id="before" class="com.gl.demo.proxy.Before"/>

3)定义切入点

为什么要定义切入点呢?其实在类中会有许多方法,但是有的方法是不需要添加额外功能的,那么定义这个切入点就可以选择为哪些方法添加额外功能。引入一个新的aop:config标签然后再这个标签中定义切入点,这里的切入点表达式execution就决定了为哪些方法添加额外功能,这个表达式时为该类所有方法添加额外功能

<aop:config><aop:pointcut id="pc" expression="execution(* *(..))"/>
</aop:config>

4)组装 

定义了切入点后肯定是要将额外功能添加进去的,所以这里就需要在配置文件中组装额外功能

<bean id="userService" class="com.gl.demo.proxy.UserServiceImpl"/>
<bean id="before" class="com.gl.demo.proxy.Before"/><aop:config><aop:pointcut id="pc" expression="execution(* *(..))"/><!-- 进行组装 --><aop:advisor advice-ref="before" pointcut-ref="pc"/>
</aop:config>

5)调用

通过前4步的过程所有的都已经准备好了,那最后一步获取到这个代理对象即可,但是我们发现这里根本就没有这个代理对象。那要怎么获取呢?

我们只需通过getBean标签获取到之前的目标类(原始类)对象即可。好,到了这里可能有的同学就会说了,获取目标类对象那不是白干了,其实不然,Spring已经帮我们加工好了这个类对象了,我们通过getBean获取到的这个类对象就已经是一个代理类对象了 。同时需要注意的是这个对象需要用之前实现的接口来接收(和之前实现同一个接口是一个道理)

public void test2() {ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");UserService userService = (UserService) ctx.getBean("userService");userService.register();userService.login();
}

在这里我们发现额外功能的添加就已经完成了

三、动态字节码技术

有的同学就会好奇,明明没有这个代理类怎么能获取到这个代理类的对象呢?其实在Spring框架运行的时候会通过动态字节码技术,在JVM中创建这个代理类,等程序结束后随着JVM会一起消失。那么问题来了,什么是动态字节码技术?

动态字节码技术:通过第三方的动态字节码框架,在JVM中创建对应类的字节码,进而创建对象,当虚拟机结束时,动态字节码随之消失(由于使用这个技术,就不需要定义类文件,所以就不会造成静态代理中类文件过多,影响项目管理的问题

四、动态代理开发简化代理开发

初看这个动态代理开发,可能会有同学认为这不是比静态代理还要麻烦吗?静态代理我都只需要写一个代理类,这里还要写额外功能、切入点、甚至还要重新组装。其实不然,这里再创建一个类并为这个类做动态代理

public interface OrderService {void showOrder();
}
public class OrderServiceImpl implements OrderService{@Overridepublic void showOrder() {System.out.println("OrderService核心功能");}
}

有了这个类之后,我想为这个类添加额外功能是不是还是要像之前那么麻烦呢?这里如果是添加已有的额外功能是不需要这么复杂的,只需要在配置文件中创建这个对象即可

<bean id="userService" class="com.gl.demo.proxy.UserServiceImpl"/>
<bean id="before" class="com.gl.demo.proxy.Before"/>
<!-- 只需要创建这个类对象即可-->
<bean id="orderService" class="com.gl.demo.proxy.OrderServiceImpl"/><aop:config><aop:pointcut id="pc" expression="execution(* *(..))"/><aop:advisor advice-ref="before" pointcut-ref="pc"/>
</aop:config>

然后进行测试,我们看一下这个类中的方法是否添加了额外功能

public void test3() {ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config2.xml");OrderService orderService = (OrderService) ctx.getBean("orderService");orderService.showOrder();
}

结果显示这个新的类中的方法也加上了相同的额外功能

那么到这里可能又会有问题了,这么一加不是所有类的所有方法都会添加上这个额外功能了?这个问题问的好!这里就可以通过切入点表达式execution来决定具体是哪个类的哪个方法添加额外功能了。。。欲知后事如何。。。

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

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

相关文章

自然语言处理---Transformer模型

Transformer概述 相比LSTM和GRU模型&#xff0c;Transformer模型有两个显著的优势&#xff1a; Transformer能够利用分布式GPU进行并行训练&#xff0c;提升模型训练效率。 在分析预测更长的文本时&#xff0c;捕捉间隔较长的语义关联效果更好。 Transformer模型的作用 基于seq…

蓝桥杯每日一题0223.10.23

第几天 - 蓝桥云课 (lanqiao.cn) 题目描述 题目分析 简单枚举&#xff08;用k来记录经过的天数&#xff09; #include<bits/stdc.h> using namespace std; bool is_ren(int n) {if(n % 400 0 || (n % 4 0 && n % 100 ! 0))return true;return false; } int …

【Android知识笔记】Webview专题

WebView 核心组件 类名作用常用方法WebView创建对象加载URL生命周期管理状态管理loadUrl():加载网页 goBack():后退WebSettings配置&管理 WebView缓存:setCacheMode() 与JS交互:setJavaScriptEnabled()WebViewClient处理各种通知&请求事件should

为什么红黑树比AVL树效率高?

文章目录 前言红黑树的提出都知道的几个定义理解红黑树的高效总结 前言 红黑树为什么这么火呢&#xff1f;大家应该都很清楚&#xff0c;面试的时候不管三七二十一&#xff0c;就问你&#xff1a;什么是红黑树&#xff0c;为什么要用红黑树&#xff1f;就好像他很懂&#xff0…

CUDA学习笔记5——CUDA程序错误检测

CUDA程序错误检测 所有CUDA的API函数都有一个类型为cudaError_t的返回值&#xff0c;代表了一种错误信息&#xff1b;只有返回cudaSuccess时&#xff0c;才是成功调用。 cudaGetLastError()用来检测核函数的执行是否出错cudaGetErrorString()输出错误信息 #include <stdi…

项目快讯|深汕特别合作区气膜羽毛球馆正式开工

“永不坍塌”的气膜运动馆 “安全”是每个行业可持续发展的核心原则、是每个企业长久生存的重要底线、是每个人追求幸福生活的基本保障。 任何新行业、新技术、新材料、新工艺的发展都需要逐步规范化的企业标准、行业标准、国家标准。 气承膜技术发展的初期&#xff0c;面临行业…

springboot+vue基于Spark的共享单车数据存储系统的设计与实现【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain

BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain----《BadNets:识别机器学习模型供应链中的漏洞》 背景&#xff1a; 许多用户将训练过程外包给云计算&#xff0c;或者依赖于经过训练的模型&#xff0c;然后根据特定的任务对模型进行微调。这…

【python】机器学习-K-近邻(KNN)算法

目录 一 . K-近邻算法&#xff08;KNN&#xff09;概述 二、KNN算法实现 三、 MATLAB实现 四、 实战 一 . K-近邻算法&#xff08;KNN&#xff09;概述 K-近邻算法&#xff08;KNN&#xff09;是一种基本的分类算法&#xff0c;它通过计算数据点之间的距离来进行分类。在…

TCP--拥塞控制

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家来访。 TCP中另一个重要的点就是拥塞控制&#xff0c;TCP是无私的当它感受到网络拥堵了&#xff0c;就…

transformer理解

李宏毅老师讲解的Transformer&#xff0c;非常简单易懂&#xff1a;https://www.youtube.com/watch? RNN存在的问题是&#xff0c;只有得到t(i)时刻的向量信息才能够计算t(i1)时刻的向量信息&#xff0c;无法实现并行化。无法实现长序列的特征信息提取&#xff0c;超过一篇文章…

【C++】哈希应用——海量数据面试题

哈希应用——海量数据面试题 一、位图应用1、给定100亿个整数&#xff0c;设计算法找到只出现一次的整数&#xff1f;2、给两个文件&#xff0c;分别有100亿个整数&#xff0c;我们只有1G内存&#xff0c;如何找到两个文件交集&#xff1f;&#xff08;1&#xff09;用一个位图…

Node.js与npm版本比对

Node.js与npm版本比对 Node.js与npm版本比对版本对比表Node版本对比 Node.js与npm版本比对 我们在项目开发过程中&#xff0c;经常会遇到公司一些老的前端工程项目&#xff0c;而我们当前的node及npm版本都是相对比较新的了。 在运行以前工程时&#xff0c;会遇到相关环境不匹…

浅谈uniapp中开发安卓原生插件

其实官方文档介绍的比较清楚而且详细,但是有时候他太墨迹,你一下子找不到自己想要的,所以我总结了一下开发的提纲,也是为了自己方便下次使用。 1.第一步,下载官方提供的Android的示例工程,然后倒入UniPlugin-Hello-AS工程请在App离线SDK中查找,之后Android studio,编译运行项目…

不会用PS抠图?教你懒人抠图法,必须学会!

相信很多小伙伴都有遇到这样的窘境——好不容易找到得素材图片&#xff0c;中间的图案很好看&#xff0c;可是特别想去掉后面的背景&#xff0c;应该如何抠图呢&#xff1f; 能够将图片中的物品或人物抠出来是一种很有用的技巧&#xff0c;可以在很多场景下应用&#xff0c;比…

MySQL -- 环境安装(CentOS7)

MySQL – 环境安装&#xff08;CentOS7&#xff09; 文章目录 MySQL -- 环境安装&#xff08;CentOS7&#xff09;一、环境安装1.卸载不必要的环境2.检查系统安装包3.卸载默认安装包4.获取MySQL官方yum源6.看看yum源能不能正常工作7.安装mysql服务 二、MySQL登录与配置1.启动My…

论文阅读 - Coordinated Behavior on Social Media in 2019 UK General Election

论文链接&#xff1a; https://arxiv.org/abs/2008.08370 目录 摘要&#xff1a; Introduction Contributions Related Work Dataset Method Overview Surfacing Coordination in 2019 UK GE Analysis of Coordinated Behaviors 摘要&#xff1a; 协调的在线行为是信息…

造车先做三蹦子220101--机器学习字符(字母、和数字识别)的“小白鼠”与“果蝇”

“0”数字字符零 的图片(16*16点阵)&#xff1a; #Letter23Digital23R231006d.pyimport torch import torch.nn as nn import torch.optim as optim #optimizer optim.SGD(model.parameters(), lr0.01) from PIL import Image from PIL import ImageDraw from PIL import Im…

取证之查看本机保存的WiFi密码

一、电脑保存有WiFi密码&#xff0c;且正常连接该WiFi 1、打开网络适配器高级选项 2、双击无线网卡&#xff0c;选择无线属性 3、点击安全&#xff0c;显示字符&#xff0c;即可看到WiFi密码。 二、电脑保存有密码&#xff0c;但是没有链接WiFi。 1、查看wlan接口上的配置文件…

OSPF的网络类型

1.3配置OSPF的网络类型 1.3.1实验3&#xff1a;配置P2P网络类型 实验需求 实现单区域OSPF的配置实现通过display命令查看OSPF的网络类型 实验拓扑 实验拓扑如图1-11所示 图1-11 配置P2P网络类型 实验步骤 步骤1&#xff1a;[1] 配置IP地址 路由器R1[2] 的配置 <Huawe…