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

news2024/12/22 20:44:47

调用者 代理对象 目标对象

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

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

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


静态代理

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

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

创建一个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没有实现增强代码功能

对这个包及子包

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ATFX汇市:美国10月CPI数据来袭,通胀率料将进一步走低

ATFX汇市:本周二21:30,美国劳工部将公布10月未季调CPI年率,前值为3.7%,预期值3.3%;9月未季调核心CPI年率将于同一时间公布,前值为4.1%,预期值4.1%。机构预期美国名义通胀率将显著下降&#xff0…

【JVM】Java内存溢出分析(堆溢出、栈溢出、方法区溢出、直接内存溢出)

📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于…

【极客时间-系列教程】Vim 实用技巧必知必会-更多常用命令:应对稍复杂的编辑任务

文章目录 更多常用命令:应对稍复杂的编辑任务光标移动文本修改文本对象选择 更多常用命令:应对稍复杂的编辑任务 几个基本的命令已经了解了,可以操作简单的任务,但一些很复杂的命令,并没有了解到,只知道几…

【C++】类和对象(4)--析构函数

一 概念 通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的? 析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销…

发布自研大模型 夸克App将迎来全面升级

国产大模型阵营再添新锐选手。11月14日,阿里巴巴智能信息事业群发布全栈自研、千亿级参数的夸克大模型,将应用于通用搜索、医疗健康、教育学习、职场办公等众多场景。夸克App将借助自研大模型全面升级,加速迈向年轻人工作、学习、生活的AI助手…

Seatunnel单机和集群部署说明

编译 编译命令 mvn clean package -pl seatunnel-dist -am -Dmaven.test.skiptrue 部署 将seatunnel-dist\target目录下的apache-seatunnel-2.3.3-SNAPSHOT-bin.tar.gz上传至服务器 解压安装包到/opt/soft/seatunnel目录下 配置环境变量 export SEATUNNEL_HOME/opt/soft/s…

【MySQL】事务(下)

文章目录 1. 各个隔离级别的演示事务隔离级别 —— 读未提交事务隔离级别—— 读提交事务隔离级别 —— 可重复读事务隔离级别 —— 串行化脏读 不可重复读 幻读的理解 2. MVCC机制读写3个记录隐藏列字段undo日志模拟MVCCread view 理论 3. 读提交与 可重复读的区别两者本质区别…

分布式锁介绍

为什么需要分布式锁 在单机部署的系统中,使用线程锁来解决高并发的问题,多线程访问共享变量的问题达到数据一致性,如使用synchornized、ReentrantLock等。 但是在后端集群部署的系统中,程序在不同的JVM虚拟机中运行,且…

ISP 处理流程

#灵感# 摆烂时间太长了,感觉知识忘光光了。重新学习,常学常新。 因为公司文档都不让摘抄、截取,所以内容是工作的一些自己记录和网络内容,不对的欢迎批评指正。 1、ISP概述 ISP是Image Signal Processor 的简称,也就…

【计算机网络】VLAN原理和配置

目录 1、VLAN的原理 1.1、什么是VLAN 1.2、为什么要使用VLAN 1.3、VLAN的三种端口类型 1.4、VLAN的划分方法 2、VLAN的配置 1、VLAN的原理 1.1、什么是VLAN VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上…

key的性能保障,事件处理器,表单控件等介绍

4-2key设置-性能的保障 不能修改原数组的方法,如果想要修改原数组,就进行重新赋值 this.items this.items.filter((item) > item.message.match(/Foo/)) keyCode键的值**key设置-性能的保障**提高性能,可以对比老的虚拟dom,一样的就留着,不一样就补上Vue默认按照"就地…

2024年孝感初中级工程师职称评审要求

孝感工程类初级职称、中级职称职称评审相关要求,满足什么条件可以评审孝感职称呢?秋禾火告诉你 什么人可以在孝感申报职称 1.在孝感本地注册登记1年以上,按规定缴纳社保的的制造业、建筑业等生产类民营企业。2.参加评审的人员与所属企业签订…

使用CXF调用WSDL(二)

简介 本篇文章主要解决了上篇文章中遗留的对象嵌套问题,要想全面解析无限极的对象嵌套需要使用递归去解决 上文链接: 使用CXF调用WSDL(一) 上文回顾 上文使用了单方法“ call() ”解决了List和基本类型(含String&…

用户登录信息如何存放

放到ThreadLocal LoginUserInfoDto 缓存登录信息的实体,我这里只放了一个手机号就够了。可以根据自己的需要修改,比如角色权限等等 package com.fox.domain.dto;/*** author * 当前登录人信息*/ public class LoginUserInfoDto {/*** 当前登录人 手机号…

什么是变更管理?对IT管理有什么帮助?

变更管理是指在最短的中断时间内完成基础架构,或服务的任一方面的变更而对其进行控制的服务管理流程。变更管理的目标是确保在变更实施过程中使用标准的方法和步骤,尽快地实施变更,以便最小化由变更所导致的业务中断,将变更对业务的影响减小到…

使用Tauri开发桌面应用

本文是对视频 Tauri入门教程[1]的学习与记录 Tauri官网[2] 对 node版本有要求 创建项目及目录介绍: 项目的目录结构如下 可以安装推荐的插件 执行npm run tauri build出错,根据 https://github.com/tauri-apps/tauri/issues/7430 执行 yarn add -D tauri-apps/cli && y…

【Windows】安装绿色版Mysql数据库 -- 可支持所有版本安装教程

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…

【Python数据结构与算法】线性结构小结

🌈个人主页: Aileen_0v0 🔥系列专栏:PYTHON学习系列专栏 💫"没有罗马,那就自己创造罗马~" 目录 线性数据结构Linear DS 1.栈Stack 栈的两种实现 1.左为栈顶,时间复杂度为O(n) 2.右为栈顶,时间复杂度O(1) 2.队列Queue 3.…

SpringCloudalibaba2

一、nacos简介 Nacos(全称为"Nano Service")是一个用于动态服务发现、配置管理和服务元数据的开源平台。它由阿里巴巴集团于2018年开源,并逐渐成为云原生应用中的重要组件之一。 Nacos提供了以下主要功能: 1. 服务发…

Mysql5.7创建远程账号和新建数据库

文章目录 Mysql5.7创建远程账号和新建数据库创建远程账号新建默认数据库默认数据库指定字符集数据库写法一写法二 查看数据库列表查看数据库的定义声明 Mysql5.7创建远程账号和新建数据库 创建远程账号 CREATE USER mm% IDENTIFIED WITH mysql_native_password BY mm1122;Que…