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

对这个包及子包

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

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

相关文章

【Python基础篇】字面量

博主:👍不许代码码上红 欢迎:🐋点赞、收藏、关注、评论。 格言: 大鹏一日同风起,扶摇直上九万里。 文章目录 一 Python中字面量的定义二 常见的字面量类型1 数字(Number)2 字符串(String)3 列表(List)4 元…

微信小程序:仅前端实现对象数组的模糊查询

效果 核心代码 //对数组进行过滤&#xff0c;返回数组中每一想满足name值包括变量query的 let result array.filter(item > { return item.name.includes(query); }); 完整代码 wxml <input type"text" placeholder"请输入名称" placeholder-styl…

前端工具nvm实现node自由

node的自由之路 前言 大家使用vue框架开发的朋友可能会遇到首次运行公司项目环境的时候&#xff0c;会出现使用npm install命令安装依赖包的时候出现各种各样的问题&#xff0c;其中很重要的一个错误原因就是因为你的nodejs版本和当时搭建环境的版本不一致造成的。今天就来给…

R语言——taxize(第一部分)

ropensci 系列之 taxize &#xff08;中译手册&#xff09; taxize 包1. taxize支持的网络数据源简介目前支持的API&#xff1a;针对Catalogue of Life&#xff08;COL&#xff09; 2. 浅尝 taxize 的一些使用例子2.1. **从NCBI上获取唯一的分类标识符**2.2. **获取分类信息**2…

网络安全基础之php开发文件上传的实现

前言 php是网络安全学习里必不可少的一环&#xff0c;简单理解php的开发环节能更好的帮助我们去学习php以及其他语言的web漏洞原理 正文 在正常的开发中&#xff0c;文件的功能是必不可少&#xff0c;比如我们在论坛的头像想更改时就涉及到文件的上传等等文件功能。但也会出…

基于SpringBoot+Vue的宿舍管理系统

基于SpringBootVue的学生宿舍管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 宿舍公告 登录界面 管理员界面 维修人员 商家界面 学生界面 摘要 摘…

Azure 机器学习:在 Azure 机器学习中使用 Azure OpenAI 模型

目录 一、环境准备二、Azure 机器学习中的 OpenAI 模型是什么&#xff1f;三、在机器学习中访问 Azure OpenAI 模型连接到 Azure OpenAI部署 Azure OpenAI 模型 四、使用自己的训练数据微调 Azure OpenAI 模型使用工作室微调微调设置训练数据自定义微调参数部署微调的模型 使用…

Python---集合中的交集 、并集 | 与差集 - 特性

用 & 来求两个集合的交集&#xff1a;-----键盘上的7上的符号&#xff0c;shift 7 同时按 用 | 来求两个集合的并集&#xff1a; -----键盘上的7上的符号&#xff0c;shift 同时按&#xff08;就是enter键上面那个|\ &#xff09; 用 - 来求两个集合的差集&#xff…

linux查看端口被哪个进程占用

linux查看端口被哪个进程占用 1、lsof -i:端口号 sudo lsof -i :22 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 661 root 3u IPv4 13882 0t0 TCP *:ssh (LISTEN) sshd 661 root 4u IPv6 13893 0t0 TCP *:ssh (LISTEN) ssh…

mysql核心知识整理

目录 聚簇索引与非聚簇索引&#xff1b; 聚簇索引&#xff1a;找到了索引就找到了需要的数据&#xff0c;那么这个索引就是聚簇索引&#xff0c;所以主键就是聚簇索引&#xff0c;修改聚簇索引其实就是修改主键。 非聚簇索引&#xff1a;索引的存储和数据的存储是分离的&#…

抖斗音_快块手直播间获客助手+采集脚本+引流软件功能介绍

软件功能&#xff1a; 支持同时采集多个直播间&#xff0c;弹幕&#xff0c;关*注&#xff0c;礼*物&#xff0c;进直播间&#xff0c;部分用户手*号,粉*丝团采集 不支持采集匿*名直播间 设备需求&#xff1a; 电脑&#xff08;win10系统&#xff09; 文章分享者&#xff1…

Kerberos认证系统

文章目录 前提知识原理第一次对话第二次对话第三次对话 总结发现 前提知识 KDC&#xff1a;由AS、TGS&#xff0c;还有一个Kerberos Database组成。 Kerberos Database用来存储用户的密码或者其他所有信息&#xff0c;请求的时候需要到数据库中查找。 AS&#xff1a;为客户端提…

WebSphere Liberty 8.5.5.9 (三)

WebSphere Liberty 8.5.5.9 将资源先下载&#xff0c;后期本地安装 下载 passwordUtilities-1.0 D:\wlp-webProfile7-java8-8.5.5.9\wlp\bin>installUtility find password 正在建立与已配置存储库的连接... 此过程可能要花几分钟完成。已成功连接至所有已配置的存储库。…

Python爬虫抓取微博数据及热度预测

首先我们需要安装 requests 和 BeautifulSoup 库&#xff0c;可以使用以下命令进行安装&#xff1a; pip install requests pip install beautifulsoup4然后&#xff0c;我们需要导入 requests 和 BeautifulSoup 库&#xff1a; import requests from bs4 import BeautifulSou…

No203.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

MySQL MHA高可用切换

MySQL MHA 1&#xff0e;什么是 MHA MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出现就是解决MySQL 单点的问题。 MySQL故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障切换操作。 MHA能在…

四、Vue3中使用Pinia解构Store

<template><div>pinia原始值: {{ Test.current }} --- {{ Test.name }}<button click"change">change</button></div><hr /><div>解构后值: {{ current }} --- {{ name }}<button click"change">change&l…

2311rust对接C

原文 为了与其他语言通信,Rust提供了(FFI)外部函数接口.FFI是Rust和C间的函数调用,与C函数调用有相同性能的零成本抽象. FFI绑定还可利用(如所有权和借用)语言功能来提供强制指针和其他资源协议的安全接口. Rust与C对话 从Rust调用C代码的简单示例开始.如下为C代码: int do…

spark调优案例分享

做了一个Spark调优案例的分享 最近在整理了Spark相关的调优案例&#xff0c;并做了以下分享:spark调优案例 &#xff0c;注意是Mac Keynote

Unity 下载Zip压缩文件并且解压缩

1、Unity下载Zip压缩文件主要使用UnityWebRequest类。 可以参考以下方法&#xff1a; webRequest UnityWebRequest.Get(Path1); //压缩文件路径webRequest.timeout 60;webRequest.downloadHandler new DownloadHandlerBuffer();long fileSize GetLocalFileSize(Path2); …