Spring框架----AOP全集

一:AOP概念的引入

首先我们来看一下登录的原理
在这里插入图片描述
如上图所示这是一个基本的登录原理图,但是如果我们想要在这个登录之上添加一些新的功能,比如权限校验
那么我们能想到的就有两种方法:
①:通过对源代码的修改实现
②:不通过修改源代码方式添加新的功能 (AOP)
在这里插入图片描述

二:AOP相关的概念

1. AOP的概述

什么是AOP的技术?
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构。
AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范。
通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(事务管理、安全检查、缓存)
为什么要学习AOP,可以在不修改源代码的前提下,对程序进行增强!!

2. AOP的优势

运行期间,不修改源代码的情况下对已有的方法进行增强
优势:

  1. 减少重复的代码
  2. 提供开发的效率
  3. 维护方便

3. AOP的底层原理

JDK的动态代理技术
1、为接口创建代理类的字节码文件
2、使用ClassLoader将字节码文件加载到JVM
3、创建代理类实例对象,执行对象的目标方法
cglib代理技术
为类生成代理对象,被代理类有没有接口都无所谓,底层是生成子类,继承被代理类。
在这里插入图片描述

三:Spring的AOP技术-配置文件方式

1. AOP相关的术语

Joinpoint(连接点) 类里面有哪些方法可以增强这些方法称为连接点
Pointcut(切入点) – 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
Advice(通知/增强)-- 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Aspect(切面)-- 是 切入点+通知 的结合,以后咱们自己来编写和配置的
在这里插入图片描述

2. 基本准备工作

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,AspectJ实际上是对AOP编程思想的一个实践.

3. AOP配置文件方式的入门

创建maven项目,坐标依赖

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!--AOP联盟--><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><!--Spring Aspects--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.2.RELEASE</version></dependency><!--aspectj--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version></dependency>
</dependencies>

创建被增强的类

// 被增强的类
public class User {//连接点/切入点public void add(){System.out.println("add......");}public void update(){System.out.println("update......");}
}

将目标类配置到Spring中

<bean id="user" class="com.aopImpl.User"></bean>

定义切面类

public class UserProxy {//增强/通知  ---》前置通知public void before(){System.out.println("before.............");}
}

在配置文件中定义切面类

<bean id="userProxy" class="com.aopImpl.UserProxy"></bean>

在配置文件中完成aop的配置

<!--配置切面-->
<aop:config><!--配置切面 = 切入点 + 通知组成--><aop:aspect ref="userProxy"><!--前置通知:UserServiceImpl的save方法执行前,会增强--><!--pointcut:后边是切入点表达式,作用是知道对对面的那个方法进行增强--><aop:before method="before" pointcut="execution(public void com.aopImpl.User.add())"/></aop:aspect>
</aop:config>

完成测试

public class DemoTest {@Testpublic void aopTest1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User) applicationContext.getBean("user");user.add();}
}

4. 切入点的表达式

再配置切入点的时候,需要定义表达式,具体展开如下:
切入点表达式的格式如下:

execution([修饰符] [返回值类型] [类全路径] [方法名 ( [参数] )])
修饰符可以省略不写,不是必须要出现的。
返回值类型是不能省略不写的,根据你的方法来编写返回值,可以使用 * 代替。

包名,类名,方法名,参数的规则如下:

例如:com.qcby.demo3.BookDaoImpl.save()
首先包名,类名,方法名是不能省略不写的,但是可以使用 * 代替
中间的包名可以使用 * 号代替
类名也可以使用 * 号代替,也有类似的写法:*DaoImpl
方法也可以使用 * 号代替
参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..比较通用的表达式:execution(* com.qcby.*.ServiceImpl.save(..))
举例2com.qcby.demo3.BookDaoImpl当中所有的方法进行增强
execution(* com.qcby.*.ServiceImpl.*(..))
举例3:com.qcby.demo3包当中所有的方法进行增强
execution(* com.qcby.*.*.*(..))
<!--配置切面-->
<aop:config><!--配置切面 = 切入点 + 通知组成--><aop:aspect ref="userProxy"><!--切入点的表达式execution() 固定的写法public 是可以省略不写的方法的返回值 int String 通用的写法,可以编写 * 不能省略不写的包名+类名 不能省略不写的,编写 * com.*方法名称 add() 可以写 *参数列表 (..) 表示任意类型和个数的参数比较通用的表达式:execution(* com.*.User.add(..))--><aop:before method="before" pointcut="execution(* com.*.User.add(..))"/></aop:aspect>
</aop:config>

5. AOP的通知类型

①: 前置通知 目标方法执行前,进行增强。

如上配置案例就是前置通知

② 环绕通知 目标方法执行前后,都可以进行增强。目标对象的方法需要手动执行。

// 环绕通知
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("before.............");//  执行被增强的方法proceedingJoinPoint.proceed();System.out.println("after.............");
}

xml配置

<aop:around method="around" pointcut="execution(* com.*.User.add(..))"/>

③. 最终通知 目标方法执行成功或者失败,进行增强。

// 最终通知
public void after() {System.out.println("after.............");
}

xml配置

<aop:after method="after" pointcut="execution(* com.*.User.add(..))"/>

④. 后置通知 目标方法执行成功后,进行增强。

//后置通知
public void afterReturning() {System.out.println("afterReturning.............");
}

xml配置

<aop:after-returning method="afterReturning" pointcut="execution(public void com.aopImpl.User.add())"/>

⑤. 异常通知 目标方法执行失败后,进行增强。(发生异常的时候才会执行,否则不执行)

//异常通知
public void afterThrowing() {System.out.println("afterThrowing.............");
}

需要改动一下切点

//连接点/切入点
public void add(){int a = 10 / 0;System.out.println("add......");
}

xml配置

<aop:after-throwing method="afterThrowing" pointcut="execution(public void com.aopImpl.User.add())"/>

4.Spring的AOP技术-注解方式

1. AOP注解方式入门程序

创建maven工程,导入坐标。编写接口,完成IOC的操作。步骤略。
编写切面类
给切面类添加注解 @Aspect,编写增强的方法,使用通知类型注解声明
①.配置xml扫描注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启注解扫描--><context:component-scan base-package="com.aopImpl"></context:component-scan></beans>

②.配置注解

@Component
public class User {//连接点/切入点public void add(){System.out.println("add......");}
}

给切面类添加注解 @Aspect,编写增强的方法,使用通知类型注解声明

@Component
@Aspect  //生成代理对象
public class UserProxy {}

③.配置文件中开启自动代理

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启注解扫描--><context:component-scan base-package="com.aopImpl"></context:component-scan><!--开启Aspect生成代理对象--><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>

④.通知类型注解
@Before – 前置通知
@AfterReturing – 后置通知
@Around – 环绕通知(目标对象方法默认不执行的,需要手动执行)
@After – 最终通知
@AfterThrowing – 异常抛出通知

@Component
@Aspect  //生成代理对象
public class UserProxy {//增强/通知  ---》前置通知@Before(value = "execution(* com.*.User.add(..))")public void before(){System.out.println("before.............");}// 环绕通知@Around(value = "execution(* com.*.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("before.............");//  执行被增强的方法proceedingJoinPoint.proceed();System.out.println("after.............");}// 最终通知@After(value = "execution(* com.*.User.add(..))")public void after() {System.out.println("after.............");}//异常通知@AfterThrowing(value = "execution(* com.*.User.add(..))")public void afterThrowing() {System.out.println("afterThrowing.............");}//后置通知@AfterReturning(value = "execution(* com.*.User.add(..))")public void afterReturning() {System.out.println("afterReturning.............");}
}

⑤.测试类

@Test
public void aopTest1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");user.add();
}

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

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

相关文章

vim相关命令

vim 三种工作模式&#xff1a;命令模式、文本模式、末行模式 命令模式&#xff1a;通过vi hello.c 命令进入i a o 、I A O、 s S 可以切换到文本模式 &#xff0c;写完后保存退出 o光标 回到下一行O光标回到上一行s删除当前字母S删除一整行A回到该行末尾处a光标回到下一个输入…

go语言操作etcd

首先在后台启动etcd 写一段go代码 package mainimport ("context""fmt"clientv3 "go.etcd.io/etcd/client/v3""time" )func main() {// 创建客户端&#xff0c;连接etcdcli, err : clientv3.New(clientv3.Config{Endpoints: []strin…

YOLOv5目标检测学习(5):源码解析之:推理部分dectet.py

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、导入相关包与路径、模块配置1.1 导入相关的python包1.2 获取当前文件的相对路径1.3 加载自定义模块1.4 总结 二、执行主体的main函数所以执行推理代码&…

手写超级好用的rabbitmq-spring-boot-start启动器

手写超级好用的rabbitmq-spring-boot-start启动器 文章目录 1.前言2.工程目录结构3.主要实现原理3.1spring.factories配置3.2EnableZlfRabbitMq配置3.3RabbitAutoConfiguration配置3.4ZlfRabbitMqRegistrar配置 4.总结 1.前言 由于springBoot官方提供的默认的rabbitMq自动装配不…

Python代码操作PPT:PowerPoint演示文稿的合并与拆分

多个PowerPoint演示文稿的处理可能会成为非常麻烦的工作。有时需要将多个演示文稿合并为一个演示文稿&#xff0c;从而不用在演示时重复打开演示文稿&#xff1b;有时又需要将单个演示文稿拆分为多个演示文稿&#xff0c;用于其他目的或进行分发。手动进行这些操作会非常麻烦&a…

阿里云环境下,从仅知的一个外网域名如何找出前端程序的部署所在和启动命令

一、背景 一个年久失修的前端项目&#xff0c;临时接到需求要迭代&#xff0c;三四年未迭代过的项目&#xff0c;交接更无从谈起。 所幸的是&#xff0c;源码还在&#xff0c;知道外网访问的入口地址。 本文试着带你一起找到该前端项目部署在哪台机器&#xff0c;以及发布的过…

opencv的approxPolyDP函数

cv2.approxPolyDP() 是 OpenCV 库中的一个函数&#xff0c;用于逼近多边形曲线。它可以将一条曲线用更少的点来表示&#xff0c;同时尽可能地保持其形状。原来是使用Douglas-Peucker算法&#xff0c;表示曲线上的点与逼近后的多边形之间的最大距离d&#xff0c;若d小于epsilon&…

SpringCloudEureka理论与入门

文章目录 1. 前置工作1.1 搭建 user-server1.1.1 pom1.1.2 po&#xff0c;mapper&#xff0c;controller1.1.3 yml1.1.4 启动类1.1.5 启动并访问 1.2 搭建 order-server1.2.1 pom1.2.2 po mapper controller1.2.3 yml1.2.4 启动类1.2.5 启动并访问 1.3 两个服务通信 2. Eureka2…

【Swing】Java Swing实现省市区选择编辑器

【Swing】Java Swing实现省市区选择编辑器 1.需求描述2.需求实现3.效果展示 系统&#xff1a;Win10 JDK&#xff1a;1.8.0_351 IDEA&#xff1a;2022.3.3 1.需求描述 在公司的一个 Swing 的项目上需要实现一个选择省市区的编辑器&#xff0c;这还是第一次做这种编辑器&#xf…

开源办公系统CRM管理系统

基于ThinkPHP6 Layui MySQL的企业办公系统。集成系统设置、人事管理、消息管理、审批管理、日常办公、客户管理、合同管理、项目管理、财务管理、电销接口集成、在线签章等模块。系统简约&#xff0c;易于功能扩展&#xff0c;方便二次开发。 服务器运行环境要求 PHP > 7.…

Mybatis Plus + Spring 分包配置 ClickHouse 和 Mysql 双数据源

目录 一、背景 二、各个配置文件总览&#xff08;文件位置因人而异&#xff09; 2.1 DataSourceConfig 2.2 MybatisClickHouseConfig &#xff08;ClickHouse 配置类&#xff09; 2.3 MybatisMysqlConfig&#xff08;Mysql 配置类&#xff09; 2.4 application.propertie…

《安富莱嵌入式周报》第334期:开源SEM扫描电子显微镜,自制编辑器并搭建嵌入式环境,免费产品设计审查服务,实用电子技术入门,USB资料汇总,UDS统一诊断

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV1om411Z714/ 《安富莱嵌入式周报》第334期&#xff1a;开源SEM…

ABCDE联合创始人和普通合伙人BMAN确认出席Hack .Summit() 2024

ABCDE联合创始人和普通合伙人BMAN确认出席Hack .Summit() 2024&#xff01; ABCDE联合创始人和普通合伙人BMAN确认出席由 Hack VC 主办&#xff0c;并由 AltLayer 和 Berachain 联合主办&#xff0c;与 SNZ 和数码港合作&#xff0c;由 Techub News 承办的Hack.Summit() 2024区…

【Paper Reading】6.RLHF-V 提出用RLHF的1.4k的数据微调显著降低MLLM的虚幻问题

分类 内容 论文题目 RLHF-V: Towards Trustworthy MLLMs via Behavior Alignment from Fine-grained Correctional Human Feedback 作者 作者团队&#xff1a;由来自清华大学和新加坡国立大学的研究者组成&#xff0c;包括Tianyu Yu, Yuan Yao, Haoye Zhang, Taiwen He, Y…

VB播放器(动态服务器获取歌词)-183-(代码+说明)

转载地址: http://www.3q2008.com/soft/search.asp?keyword183 VBASP vb动态从服务器读取歌词 VB asp交互 程序, 模式不一样, 与普通的MP3播放器不一样, 这个是可以实现歌词从服务器上查询功能的. 看好了在咨询 我可以給您演示 目  录 前  言 1 1 . 简述 2 1.1 开发…

阿里云国际DDoS高防接入配置最佳实践

业务接入DDoS高防产品后&#xff0c;可以将攻击流量引流到DDoS高防&#xff0c;有效避免业务在遭受大流量DDoS攻击时出现服务不可用的情况&#xff0c;确保源站服务器的稳定可靠。本文九河云的接入配置和防护策略最佳实践&#xff0c;在各类场景中使用DDoS高防更好地保护您的业…

Linux系统下基于VSCode和Cmake进行C++开发

目录 简介一、GCC编译器1.1创建cpp文件1.2编译过程1.3g重要编译参数 二、GDB调试器三、IDE-VScode3.1 VSCode常用快捷键3.2 swap测试 四、CMake4.1CMake介绍4.2 CMake语法特性介绍4.3 CMake重要指令和常用变量4.4 CMake编译流程4.5CMake代码实践 五、使用VSCode进行完整项目开发…

【JavaScript】面试手撕柯里化函数

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 引入柯里化定义实现快速使用柯里化的作用提高自由度bind函数 参考资料 引入 上周…

开源绘图工具 PlantUML 入门教程(常用于画类图、用例图、时序图等)

文章目录 一、类图二、用例图三、时序图 一、类图 类的UML图示 startuml skinparam classAttributeIconSize 0 class Dummy {-field1 : String#field2 : int~method1() : Stringmethod2() : void } enduml定义能见度&#xff08;可访问性&#xff09; startumlclass Dummy {-f…

ES6(一):let和const、模板字符串、函数默认值、剩余参数、扩展运算符、箭头函数

一、let和const声明变量 1.let没有变量提升&#xff0c;把let放下面打印不出来&#xff0c;放上面可以 <script>console.log(a);let a1;</script> 2.let是一个块级作用域,花括号里面声明的变量外面找不到 <script>console.log(b);if(true){let b1;}//und…