【Spring从入门到实战】第 4 讲:SpringAOP实现以及原理

本文已收录于专栏
🌲《Spring从入门到实战》🌲

专栏前言

   大家好,我是执梗。本专栏将从Spring入门开始讲起,详细讲解各类配置的使用以及原因,到使用SpringBoot进行开发实战,旨在记录学习生活的同时也希望能帮到大家,如果对您能有所帮助,还望能点赞关注该专栏,对于专栏内容有错还望您可以及时指点,非常感谢大家 🌹。

目录

  • 专栏前言
  • 1.AOP是什么?
  • 2.为什么要用AOP?
  • 3. AOP的组成
    • 1.切面(Aspect)
    • 2.连接点(Join Point)
    • 3.切点(Pointcnt)
    • 4.通知(Advice)
  • 4.SpringAOP的实现
    • 1.导入AOP依赖
    • 2.定义切面和切点
  • 5.AOP的实现原理

1.AOP是什么?

  AOP:面向切面编程,主要是一种思想,将某一类事情来进行集中的处理。 可以减少冗余代码,而且提高代码的解耦合,可重用性以及可维护性。
  SpringAOP则是AOP思想的一种具体实现,它是一个框架,通过它我们可以利用AOP思想来设计代码。

2.为什么要用AOP?

  举一个常见的场景,我们在做后台系统时,除了登录和注册两个板块是不需要登录验证即可访问之外,其余的页面都应该必须先验证用户登录状态,如果未登录是不允许访问的。如果按照老版本的做法,对于每一个 Controller 我们都需要去验证用户登录状态,那么随着工程的壮大,这种判断代码会越来越多,我们维护的成本或会越来越高。
  这种应用单一,且需要被多处调用的功能,就可以考虑 AOP 来统一进行处理达到优化目的。
  除了登录验证这个功能外,AOP还可以解决以下这些场景:

  • 统一日志记录
  • 统一方法执行时间统计
  • 统计的返回格式设置
  • 统一的异常处理
  • 事务的开启和提交等

3. AOP的组成

  由于都是英语直译过来,下面的名词按中文理解可能会有点抽象,不过大家知道是啥作用即可。

1.切面(Aspect)

切面是横切关注点的实现。在 Spring AOP 中,一个切面通常是一个 Java 类,它包含一些通知(Advice)和一个切入点(Pointcut)

切面可以理解为 AOP 实现某个功能的集合

2.连接点(Join Point)

连接点是程序执行过程中能够插入切面的点。在 Spring AOP 中,连接点通常是方法调用或方法执行的时刻。

连接点相当于需要被增强的某个 AOP 功能的所有⽅法。

3.切点(Pointcnt)

切入点定义了哪些连接点会触发通知。它使用切入点表达式来匹配连接点。

切点相当于保存了众多连接点的⼀个集合(如果把切点看成⼀个表,而连接点就是表中⼀条⼀条的数据)

4.通知(Advice)

通知是切面在连接点处执行的代码。SpringAOP中有五种类型的通知,通常我们可以在方法上使用注解来使方法称为对应的通知方法:

  • 前置通知使用 @Before:通知方法会在目标方法返回后调用。
  • 后置通知使用 @After:通知方法会在目标方法抛出异常后调用。
  • 返回之后通知使用 @AfterReturning:通知方法会在目标方法返回后调用
  • 抛异常后通知使用 @AfterThrowing:通知方法会在目标方法抛出异常后调用。
  • 环绕通知使用 @Around:通知包裹了被通知的方法,在被通知的方法通知之前和调用之后执行自定义的行为
    在这里插入图片描述

4.SpringAOP的实现

  接下来我们来初步实现以下 AOP的 功能,目标是去拦截 UserController 里面的方法,并执行相对应的通知事件。

1.导入AOP依赖

pom.xml添加依赖:

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.定义切面和切点

  切点指的是我们需要处理的某一类问题,比如用户权限验证就是一个问题,切点定义的是某一类问题
  SpringAOP切点的定义如下,在切点中需要定义拦截规则,代码实现如下:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;


@Aspect  //表明当前类是一个切面
@Component
public class UserAspect {
    //定义切点(设置拦截规则)
    @Pointcut("execution(* com.example.springbootaop.controller.UserController.*(..))")
    public void pointcut() {
    }


    /*
     *   定义poincut切点的前置通知
     * */
    @Before("pointcut()")
    public void doBefore() {
        System.out.println("前置通知被执行了");
    }
 	/*
    *   return 之前返回
    * */
    @AfterReturning("pointcut()")
    public void doAfterReturning(){
        System.out.println("执行了 doAfterReturning 方法");
    }

    /*
     *   后置通知
     * */
    @After("pointcut()")
    public void doAfter() {
        System.out.println("后置通知被执行了");
    }
}

注意这里的注解@Pointcut里的参数是我们需要拦截的路径,是AspectJ表达式的写法,这里不过多讲解。
配置Controller

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user/")
public class UserController {

    @RequestMapping("/sayhi")
    public String sayHi(){
        System.out.println("sayhi 方法被执行了");
        return "你好,世界";
    }
}

当我们访问后,回答控制台查看打印:
在这里插入图片描述
从打印顺序来看是符合预期的。
@AfterThrowing会在抛出异常的时候执行,我们

 @AfterThrowing("pointcut()")
    public void doAfterThrowing() {
        System.out.println("执行了 doAfterThrowing 方法");
 }

更改Controller里的代码,使其产生一个除零异常我们来测试以下:

@RestController
@RequestMapping("/user/")
public class UserController {
    @RequestMapping("/sayhi")
    public String sayHi(){
        int a=10/0;
        return "你好,世界";
    }
}

在这里插入图片描述

这里我们发现,即使出现异常,后置方法仍然会执行。

5.AOP的实现原理

  SpringAOP是构建在动态代理基础上,因此它仅支持局限于方法级别的拦截

  1. 基于代理模式实现:Spring AOP使用代理模式,在目标对象与通知对象之间创建一个代理对象,拦截目标对象的方法调用,并在方法调用前后执行通知逻辑。
  2. 动态代理实现:Spring AOP使用Java动态代理(Proxy)或者CGLIB动态代理来创建代理对象,具体使用哪种动态代理方式取决于目标对象是否实现了接口。如果目标对象实现了接口,Spring AOP会使用Java动态代理,否则会使用CGLIB动态代理。
    在这里插入图片描述

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

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

相关文章

IDEA常用插件列表

一 背景 IDEA常用插件列表&#xff0c;用来提供工作效率。你都安装了吗 IntelliJ IDEA 默认安装并提供了非常多的工具&#xff0c;比如 Maven Integration、Markdown support、SSH Remote Run 等。其中有很多好用&#xff0c;但是不为人知的工具。 二 插件列表 阿里代码规约…

Linux基础命令大全(上)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…

pytorch-在竞赛中去摸索用法,用房价预测比赛了解数据处理流程

实战Kaggle比赛&#xff1a;房价预测 让我们动手实战一个Kaggle比赛&#xff1a;房价预测House Prices - Advanced Regression Techniques | Kaggle。本文将提供未经调优的数据的预处理、模型的设计和超参数的选择。通过动手操作、仔细观察实验现象、认真分析实验结果并不断调…

【算法入门】字符串基础

目录 一.字符串引言1.字符串基础二.洛谷P5734详解1.字符串相关库函数&#x1f4ab;&#xff08;1&#xff09; strcpy函数 &#x1f4ab;&#x1f4ab;&#xff08;2&#xff09; strcat函数 &#x1f4ab;&#x1f4ab;&#xff08;3&#xff09;strstr函数 &#x1f4ab;2.题…

JavaScript的事件传播机制

你在学习和编写JavaScript时可能听说过事件冒泡&#xff08;event bubbling&#xff09;。它会发生在多个元素存在嵌套关系&#xff0c;并且这些元素都注册了同一事件(例如click)的监听器时。 但是事件冒泡只是事件机制的一部分。它经常与事件捕获(event capturing)和事件传播…

ChatGPT的N种用法(持续更新中。。。)

目录前言一、语法更正二、文本翻译三、语言转换3-1、Python-->JAVA四、代码解释-1五、代码解释-2六、修复代码错误六、作为百科全书七、信息提取七、好友聊天八、创意生成器8-1、VR和密室结合8-2、再结合AR九、采访问题9-1、采访问题清单9-2、采访问题清单并给出相应答案十、…

2分钟彻底搞懂“高内聚,低耦合”

&#x1f497;推荐阅读文章&#x1f497; &#x1f338;JavaSE系列&#x1f338;&#x1f449;1️⃣《JavaSE系列教程》&#x1f33a;MySQL系列&#x1f33a;&#x1f449;2️⃣《MySQL系列教程》&#x1f340;JavaWeb系列&#x1f340;&#x1f449;3️⃣《JavaWeb系列教程》…

一个nginx的小项目,不写代码,实现在局域网内访问其他电脑的网页

准备工作 下载nginx //官网 https://nginx.org/en/download.html //直接下载 https://nginx.org/download/nginx-1.23.3.zip解压 下载一个html项目&#xff0c;或者自己随便写一个 我是直接下载的&#xff0c;然后使用的是第一个01 https://gitee.com/StarPort/HTML_CSSTe…

从SpringBoot生命周期来看服务注册到Eureka/Nacos的时机

文章目录服务注册入口1、Eureka2、Nacos总结服务注册入口 无论是将服务注册到哪种服务注册中心&#xff0c;服务注册的时机都是在AbstractApplicationContext#finishRefresh()方法中&#xff1b;即Spring容器加载完成、Web服务启动之后&#xff1b; 从SpringCloud规范来看&am…

C语言实现学生成绩管理系统思考

学生成绩管理系统思考 作业要求&#xff1a; 目录 思路 基本函数 学习理解大佬的代码&#xff1a; 完成作业&#xff1a; 思路 学生成绩管理系统&#xff0c;首先要初始化系统&#xff0c; 用C语言做学生实验管理系统要求实现对某班学生3门课程&#xff08;包括语文、数…

Python 基础教程【2】:条件语句和循环语句

本文已收录于专栏&#x1f33b;《Python 基础》文章目录1、流程控制语句1.1 顺序语句1.2 条件语句1.2.1 if语句注意事项1.2.2 三元运算符1.2.3 自动类型转换1.3 循环语句1.3.1 while 循环1.3.2 for-in 循环1.3.3 for...else 循环1.3.4 break 和 continue 的区别2、实践——猜数…

SpringBoot:手写一个 SpringBoot Starter

声明&#xff1a;原文作者&#xff1a;yuan_404 文章目录1. 说明2 . 编写启动器3 . 新建项目测试自己写的启动器1. 说明 启动器模块是一个 空 jar 文件&#xff0c;仅提供辅助性依赖管理&#xff0c;这些依赖可能用于自动装配或者其他类库 命名归约&#xff1a; 官方命名&…

面试必会-MySQL篇

1. Mysql查询语句的书写顺序Select [distinct ] <字段名称>from 表1 [ <join类型> join 表2 on <join条件> ]where <where条件>group by <字段>having <having条件>order by <排序字段>limit <起始偏移量,行数>2. Mysql查询语…

14个你需要知道的实用CSS技巧

让我们学习一些实用的 CSS 技巧&#xff0c;以提升我们的工作效率。这些 CSS 技巧将帮助我们开发人员快速高效地构建项目。 现在&#xff0c;让我们开始吧。 1.CSS :in-range 和 :out-of-range 伪类 这些伪类用于在指定范围限制之内和之外设置输入样式。 (a) : 在范围内 如…

SQL代码编码原则和规范

目录专栏导读1、先了解MySQL的执行过程2、数据库常见规范3、所有表必须使用Innodb存储引擎4、每个Innodb表必须有个主键5、数据库和表的字符集统一使用UTF86、查询SQL尽量不要使用select *&#xff0c;而是具体字段7、避免在where子句中使用 or 来连接条件8、尽量使用数值替代字…

植物大战 仿函数——C++

容器适配器 容器适配器不支持迭代器。栈这个东西&#xff0c;让你随便去遍历&#xff0c;是不好的。他是遵循后进先出的。所以他提供了一个街头top取得栈顶数据。 仿函数 仿函数&#xff08;functor&#xff09;是C中一种重载了函数调用运算符&#xff08;operator()&#x…

2023年网络安全最应该看的书籍,弯道超车,拒绝看烂书

学习的方法有很多种&#xff0c;看书就是一种不错的方法&#xff0c;但为什么总有人说&#xff1a;“看书是学不会技术的”。 其实就是书籍没选对&#xff0c;看的书不好&#xff0c;你学不下去是很正常的。 一本好书其实不亚于一套好的视频教程&#xff0c;尤其是经典的好书…

计算机网络概述

目录前言计算机网络的形成<font colorblue>计算机定义与分类计算机网络的定义计算机网络的分类1.按网络的覆盖范围分类2.按网络采用的传输技术分类按网络的拓扑分类计算机网络的组成计算机网络体系结构层次结构体系ISO/OSI 参考模型Tcp/ip体系结构这就是计算机网络的基础…

大数据框架之Hadoop:MapReduce(五)Yarn资源调度器

Apache YARN (Yet Another Resource Negotiator) 是 hadoop 2.0 引入的集群资源管理系统。用户可以将各种服务框架部署在 YARN 上&#xff0c;由 YARN 进行统一地管理和资源分配。 简言之&#xff0c;Yarn是一个资源调度平台&#xff0c;负责为运算程序提供服务器运算资源&…

Linux- 系统随你玩之--玩出花活的命令浏览器上

文章目录1、背景2、命令浏览器2.1、命令浏览器介绍2.2、特点2.3 常用功能选项3、实操3.1、使用 wget 下载文件3.2、 断点续传3.3、镜像整个站点4、 总结1、背景 一位友人说他有台服务器&#xff0c;需要下载一个文件&#xff0c;但是没有视窗界面与下载工具&#xff0c;怎么办…