11-13 /11-14代理模式 AOP

调用者 代理对象 目标对象

代理对象除了可以完成核心任务,还可以增强其他任务,无感的增强

代理模式目的:
不改变目标对象的目标方法的前提,去增强目标方法

分为:静态代理,动态代理


静态代理

有对象->前提需要有一个类,那么我们可以事先写好一个类,他是一个代理类

程序员为目标类编写一个代理类(用于增强目标方法),要求目标类和代理类实现同一个接口,让用户感觉代理和目标是一类的东西,无感的

创建一个maven

创包com.fs.staticproxy

创目标类和代理类的统一接口:

创建目标类:

目标方法之前可能需要扩展 日志记录 权限管理等等  这些不是非核心代码、功能,可能就是一些简单的业务,但是又不省略,但是他又不是固定的,时可变的,而卸载目标类就是硬代码

 创建代理类:代理代理 -> 我中有你  有一个目标对象

出现问题:重复

解决办法:我(代理类)中有(目标类)你

给属性复赋值:构造方法 set方法 实现了代理类增强方法

测试类(调用者):

需要改变时,目标对象、目标类不需要改变,核心代码不用改变,,只需要改代理对象

缺点:多个接口要实现相同的方法,增强相同的方法,那么需要创建很多个代理类,这是不对的,

核心接口加方法,代理类也要加方法实现对应的方法,目标对象和代理类都需要维护

导致静态代理的缺点问题根源->代理类的存在

动态代理

这个静态代理类不要你写,通过code动态生成

存的是BussinessInterface接口  -> 使得这个代理类代理的范围更加多一点,不再只有Buiness这一个实现类的代理类,他可以实现只要你的目标类实现BussinessInterface这一类   统一接口下面所有的不同类型的这个目标类都可以被我的代理类所代理

站在使用者这边,我们在乎的是代理类对象,而不是代理类,基于这个,

jdk可以自动生成生成这个代理类对象,确实可以实现,我要代哪一个接口,接口告诉我,然后jdk有一个api方法,经过这个api方法的时候,他就可以得到一个api代理对象,此时我就不需要代理类了,我直接用这个代理对象就行了

通过接口的class对象,创建一个实现类的Class对象,再通过反射得到实现类的对象(这个实现类是动态的,创建的是不存在的实现类对象)

jdk提供了通过接口的Class对象,创建一个实现类(动态,不存在)的Class对象的API:java.lang.reflect .Proxy类:

Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。以class造class

接口不能创建方法,因为它没有构造方法(用于创建对象),,现在想创建对象,

根据接口的创建对象,没有这个类,没有这个构造方法,也可以通过反射得到对象,通过反射得到Class对象,调用它的构造方法得到对象

我们现在需要一个类 class  由于接口不能创建构造方法,所以我们需要根据接口的class来克隆/生成一个类的class,这个类的classs是构造方法的class根据  根据接口的class对象生成类的class对象,这个类的class对象复制了接口的所有的方法,同时他又有构造方法。

创建对象的核心:前提条件就是要有该类的Class对象,(也可以通过new的方式去拿)拿到之后我么就可以通过反射创建对象,当然底层还是调用构造方法,比如接口类没有构造方法就无法创建对象

动态代理(基于接口)

创一个类:

$ -> 动态类

Class Proxy.getProxyClass(),得到Class对象对应类是Proxy的子类,而且得到Class对应类的模版参考Proxy类

Proxy的构造方法

子类构造方法(由于父类构造方法私有,不能调用父类构造方法)

父类只提供给这个有参构造方法:

$Proxy4:生成一个如下构造方法  虽然是受保护类型,但是

 (上面做了,通过接口的class对象构造代理类的实现对象)

 代理对象执行目标方法他会在底层调用invoke()方法

只要我在invoke写核心code 那么我就可以重写excute的逻辑code

为什么代理对象执行目标方法,底层还调用lnvocationHandler的invoke()?

为什么还要proxy.excute()和invoke()分开呢?

当我们使用动态代理时,代理对象执行目标方法时底层还调用`InvocationHandler`的`invoke()`方法是因为代理对象并不知道具体要执行的目标方法是什么,以及是否需要添加额外的逻辑。因此,代理对象将目标方法的调用委托给了`InvocationHandler`来处理。

代理对象在执行目标方法时,会将目标方法的信息(包括方法名、参数等)传递给`InvocationHandler`的`invoke()`方法。`InvocationHandler`可以根据这些信息进行额外的操作,比如在方法调用前后进行日志记录、权限验证等。

为什么还要将`proxy.execute()`和`invoke()`分开呢?这是因为动态代理的实现是通过`Proxy`类和`InvocationHandler`接口来配合完成的。`Proxy`类负责生成代理对象,而`InvocationHandler`接口负责处理方法调用。

`Proxy`类生成的代理对象并不直接实现目标接口的方法,而是在代理对象的方法中调用`InvocationHandler`的`invoke()`方法。这样的设计可以将代理对象的方法和`InvocationHandler`的逻辑分离,使得代理对象可以专注于代理的行为,而不需要关心具体的方法实现。

通过将方法调用和逻辑处理分开,我们可以更灵活地控制代理对象的行为。可以在`InvocationHandler`的`invoke()`方法中添加额外的逻辑,也可以根据需要选择不同的`InvocationHandler`实现,实现动态切换和扩展代理对象的功能。

总结来说,代理对象执行目标方法时底层还调用`InvocationHandler`的`invoke()`方法是为了将方法调用和逻辑处理分离,以实现更灵活的代理行为。这样的设计使得代理对象可以专注于代理行为,而不需要关心具体的方法实现。同时,通过分离方法调用和逻辑处理,我们可以实现更高级的代理功能,如动态切换代理行为或添加额外的逻辑。

proxy.excute();//但是没看到它重写的代码 

匿名类部类

lamba表达式(jdk8)

动态代理:  getMappper使用的动态代理

传接口的class对象,得到的是接口的实现类对象,再得到构造方法,再new instance得到实例对象

得到实现类的构造方法

得到接口的实现类对象之后,再实现代理

替换之前写的

  Proxy类得到接口的代理类对象,并且还需要对接口的抽象方法进行重写,写在invotionHandler接口对象的invoke()当中

问题: Proxy类得到接口的代理类对象,并且还需要对接口的抽象方法进行重写,重写方法的逻辑代码,在lnvocationHandler接口对象的invoke0中
Proxy:创建代理对象
lnvocationHandler接口对象的invoke()对方法重写的

为了创建代理对象与编写方法逻辑代码方法体分离,解耦
我们在创建代理对象的时候,可以不实现方法体,在后期根据你实际需求,传递方法体

开始代理

此时只能指定代理指定的代理类对象

现在改一改

对任何接口的目标类进行增强

所有:

对他增强

proxy.fun();

实现增强

配置文件优化,把增强代码出来,分离,形成一个增强类,

jdk实现的动态代理要求目标类一定要实现接口,所以这也是一个其动态代理的一个缺点所在

第二种方式:

使用第三方的CGLIB,它生成的代理类,这个类会继承目标类,所以他不会管这个目标类有没有实现接口,但是它要i求不能实现fina关键字(继承不能)

jdk自带的动态管理,要求目标类一定要实现接口,没有实现接口那么就是用CGLIB,记得不要使用final关键字就行了

动态代理的优点

优点:

1.没有代理类,解决静态代理的代理类暴增的问题

2.解决了静态代理的重复代码问题

3.创建代理对象与重写方法逻辑代码解耦

缺点:

增强代码与目标方法是通过硬编码的方式组织在一起,如果需要动态生成增强代码,需要修改代码

SpringAop

AOP:面向切面编程,对OOP的补充。不改变目标方法代码前提,增强目标方法

横切面:切面 目标方法/目标类->独立  增强类/增强方法->独立  两者独立,目标类前后都有

增强类/增强方法 但是在运行的时候,通过AOP或者其他技术,感觉这三个玩意是一起的,面向横切面

OOP:面向对象编程

userSer。。。  只要写目标类的核心代码  配置/注解的时候

AOP使用场景:

  • 事务控制 下单流程(生成订单insert 支付状态update 商品库存数量update)
  • 日志记录 (log4j) (开发中的日志表,记录用户行为信息)
  • 权限控制
  • 性能分析
  • 缓存操作        (实际缓存是基于Redis的技术)

Spring两大核心

  • IOC/DI:依赖对象之间的解耦
  • AOP:目标类与增强类的解耦   关注的是横切面的一个解耦

        AOP采取横向抽取机制((动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。
        主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。
        简单的说,AOP的作用就是保证开发者在不修改源代码的前提下,为系统中的业务组件添加某种通用功能

SpringAOP开始使用

基于AspectJ这个AOP实现的

2.编写目标类目标方法

3.编写增强类(通知类)中增强方法

基于AspectJ方式,对增强类没有任何要求,就是一个普通类

增强:

        前置增强

        后置增强

        最终增强

        日志增强

        ......

4.织入,把目标方法与增强方法编织在一起,Spring提供AOP提供相关配置和注解

通过配置之后,这个before方法先于目标方法执行

delete没有实现增强代码功能

对这个包及子包

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

游戏缺失XINPUT1_3.dll的解决方法,一招搞定dll报错问题

当您尝试玩游戏或运行某个软件时,可能会遇到系统报错提示“XINPUT1_3.dll丢失”。这个错误通常是由于缺少或损坏了XINPUT1_3.dll文件导致的。“XINPUT1_3.dll”是一个动态链接库(Dynamic Link Libraries,简称DLL)文件。它是微软公…

Blazor 附件上传和下载功能

效果图 page "/uploadFile" inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment WebHostEnvironment inject ToastService ToastService inject DownloadService DownloadService<h3>UploadFile</h3><Button OnClick"ButtonClick" C…

Linux虚拟机的安装

文章目录 1. 准备虚拟机2. 安装所需软件3. 上传项目文件4. 配置项目环境5. 安装项目依赖6. 数据库设置7. 启动项目8. 测试项目9. 设置域名和DNS&#xff08;可选&#xff09;10. 定期维护11. 使用反向代理&#xff08;可选&#xff09;12. 安全性加固13. 使用容器化技术&#x…

间歇性工作的时钟波形对行sdc约束怎么写

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 如下图&#xff0c;紫色部分波形间歇式工作&#xff0c;如果要写约束应该怎么写&#xff1f; 答&#xff1a;按照最小周期写即可&#xff0c;只看active的部分&#xff0c;至于…

springboot+maven多环境动态配置,以及编译失败的解决方案

一、前言 在我们的项目开发过程中一般会有多套的环境&#xff0c;比如比较常见的会有三套&#xff1a; dev &#xff08;研发环境&#xff09;&#xff0c;test(测试环境)&#xff0c;prod&#xff08;生产环境&#xff09;。 application.yml 是主配置文件&#xff0c;当在不…

【带头学C++】----- 六、结构体 ---- 6.6 结构体的指针成员

6.5结构体指针变量 结构体的指针变量:本质是变量只是该变量保存的是结构体变量的地址 6.5.1结构体指针变量的定义 通过指针&#xff0c;可以访问到我们结构体变量的值 可以通过 -> 符号 访问到结构体变量 6.5.2 结构体数组元素的指针变量 指针变量保存结构体数组元素…

Vue3弹性布局(Flex)

效果如下图&#xff1a;在线预览 APIs 参数说明类型默认值必传width区域总宽度string | number‘auto’falseverticalflex 主轴的方向是否垂直&#xff0c;vertical 使用 flex-direction: columnbooleanfalsefalsewrap设置元素单行显示还是多行显示&#xff1b;参考 flex-wrap…

《线性代数》科教版教材必会习题

出一期比较尴尬的博客——有关线代教材的课后题总结~ 之所以说尴尬&#xff0c;主要有两个主要原因&#xff1a;这本科教版第三版的教材&#xff0c;整体看起来并不是那么舒服&#xff0c;甚至被我们的老师吐槽过&#xff0c;更好地选择时同济版的那本紫书——我们学校的新生这…

AWTK实现汽车仪表Cluster/DashBoard嵌入式GUI开发(六):FREERTOS移植

前言: 一般的GUI工程都需要一个操作系统,可能是linux,重量级的,也可能是FreeRTOS,轻量级的。 一句话理解那就是工程就是FreeRTOS task任务的集合。 一个main函数可以看到大框架: 很显然,除了第一个是硬件配置的初始化,中间最重要的部分就是要创建任务。而一个任务主…

扫码下载视频怎么做?适用多种格式视频文件

现在将视频制作二维码来展示的应用场景越来越多&#xff0c;企业、学校、个人、产品等等很多内容都会使用视频二维码。可能有些小伙伴用来生成二维码的视频只能查看不能下载&#xff0c;导致在使用时受到限制&#xff0c;那么想要制作可以下载视频二维码的小伙伴&#xff0c;下…

【unity】网格描边方法

【unity】网格描边方法 介绍对模型四边网格的三种描边方法&#xff1a;包括纯Shader方法、创建网格方法和后处理方法。于增强场景中3D模型的轮廓&#xff0c;使其在视觉上更加突出和清晰。这种效果可以用于增强三维场景中的物体、角色或环境&#xff0c;使其在视觉上更加吸引人…

Javaweb开发 利用servlet+jsp+jdbc+tomcat数据库实现登录功能

前言&#xff1a;很久没更新了&#xff0c;今天给大家分享一个Java web的小案例&#xff0c;是一个登录页面&#xff0c;利用Login控制类和JDBC连接数据库&#xff0c;并判断用户名密码是否正确&#xff0c;项目最终部署在Tomcat上。 先看效果 正文 一、前期工作 1.首先我们…

云课五分钟-02第一个代码复现-终端甜甜圈C++

前篇 云课五分钟-01课程在哪里-无需安装网页直达- 代码复现通过云课&#xff0c;会非常快捷。 视频 云课五分钟-02第一个代码复现-终端甜甜圈C 文本 如何使用g 使用g编译和链接C程序的基本步骤如下&#xff1a; 编写源代码&#xff1a;首先&#xff0c;你需要编写C源代码&…

Docker学习——⑧

文章目录 1、什么是 Docker Compose(容器编排)2、为什么要 Docker Compose&#xff1f;3、Docker Compose 的安装4、Docker Compose 的功能和使用场景5、Docker Compose 文件&#xff08;docker-compose.yml&#xff09;5.1 文件语法版本5.2 文件基本结构及常见指令 6、Docker …

【C#学习】串口编程

文章目录 第一步&#xff1a;加入串口控件第二步&#xff1a;加入模块第三步&#xff1a;编写相关函数功能获取所有串口资源设置和打开关闭串口发送字符串&#xff08;string&#xff09;发送byte检查串口状态接受byte查询所有可用串口 第一步&#xff1a;加入串口控件 第二步&…

Elasticsearch7 入门 进阶

1、全文检索 1.1、数据分类 按数据分类的话&#xff0c;主要可以分为以下三类&#xff1a; 结构化数据&#xff1a;固定格式、有限长度&#xff0c;比如mysql存的数据非结构化数据&#xff1a;不定长、无固定格式&#xff0c;比如邮件、Word文档、日志等半结构化数据&#xf…

Git 工作流程、工作区、暂存区和版本库

目录 Git 工作流程 Git 工作区、暂存区和版本库 基本概念 Git 工作流程 本章节我们将为大家介绍 Git 的工作流程。 一般工作流程如下&#xff1a; 克隆 Git 资源作为工作目录。在克隆的资源上添加或修改文件。 如果其他人修改了&#xff0c;你可以更新资源。在提交前查看…

抖音小程序开发全攻略:如何规划项目和选择合适的开发团队

在数字化时代&#xff0c;抖音小程序成为企业推广和服务的重要渠道。本文将为您提供抖音小程序开发的全面攻略&#xff0c;重点介绍如何规划项目和选择合适的开发团队&#xff0c;并附有一些关键的技术代码示例。 1. 项目规划 在开始抖音小程序开发之前&#xff0c;详细的项…

11月14日星期二今日早报简报微语报早读

11月14日星期二&#xff0c;农历十月初二&#xff0c;早报微语早读。 1、江西南城县&#xff1a;限时发放购房补贴政策&#xff0c;三孩家庭每平方米最高补贴500元&#xff1b; 2、2023年中国内地电影市场累计票房突破500亿元&#xff1b; 3、市场监管总局&#xff1a;在全国…

读写分离(基于mycat)和全同步复制

一、mycat实现读写分离&#xff08;VIP机制&#xff09; &#xff08;一&#xff09;配置主从复制 &#xff08;二&#xff09;部署mycat 1、安装Java 2、下载mycat安装包 3、解压mycat包 4、设置变量环境 5、启动mycat &#xff08;三&#xff09;客户端连接数据库 1、安装…