【JavaEE进阶】——第七节.Spring AOP统一功能处理(切面、切点、连接点、通知)

news2024/12/26 9:18:43

作者简介:大家好,我是未央;

博客首页:未央.303

系列专栏:JavaEE进阶

每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!

文章目录

前言

一、 AOP的前置知识

1.1 什么是AOP

1.2 AOP的作用 

二、SpringAOP的实现

2.1 添加SpringAOP框架支持

2.2 定义切面(Aspect)

2.3 定义切点(Pointcut)

2.4 定义通知(Advice)

三、实例展示(计时器)

代码实现 

总结



 

前言

今天我们将介绍有关Spring AOP统一功能处理的内容


一、 AOP的前置知识

1.1 什么是AOP

Aop是一种统一处理某一问题的思想,比如验证用户是否登录

验证用户是否登录实例分析:

在为使用Aop的时候,我们需要验证的每个类(页面)都有调用验证方法,而使用了Aop后,我们只需要在某处把验证规则配置一下,就可以实现对需要验证的类的登录验证,不用每个类在重复调用验证方法了。

Aop由切面、切点、连接点、通知组成;

切面:

切面表示我们要统一处理的功能(类)——比如验证用户是否登录;

切点:

切点则是是否进行Aop拦截的规则(哪些页面不需要进行登录验证,哪些需要,这种规则)

连接点:

连接点则是具体到哪些页面需要进行拦截(哪些类需要调用登录验证方法)

通知:

通知则是验证用户是否登录的那个具体方法实现(代码细节)——》前置通知,后置通知 ;

而AOP是一种思想,而SpringAOP是这个框架对AOP思想的实现(类似IoC和DI) 


1.2 AOP的作用 

AOP由以下四部分组成:

  1. 切面(Aspect):定义AOP业务类型(表示当前AOP是做什么的)。
  2. 连接点(Join Point):有可能调用AOP的地方就叫做一个连接点。
  3. 切点(Pointcut):定义AOP拦截规则。
  4. 通知(Advice)【增强方法】:定义什么时候干什么事(代码的实现细节,前后顺序)。

通知(Advice):

定义的是被拦截的方法具体要执行的业务,比如用户登录权限验证方法就是具体要执行的业务。

通知的分类方法:

  • a) 前置通知:在拦截的目标方法之前执行的通知(事件)
  • b)后置通知:在拦截的目标方法之后执行的通知(事件)
  • c)返回之后通知:在拦截的目标方法返回数据之后通知
  • d)抛出异常之后的通知:在拦截的目标方法抛出异常之后执行的通知
  • e)环绕通知:在拦截方法执行前后都执行的通知。

AOP整个组成部分的概念如下图所示,以多个页面都要访问用户登录权限为例 :


二、SpringAOP的实现

2.1 添加SpringAOP框架支持

在我们的项目的pom.xml中添加支持

这个时候,我们就需要借助 中央仓库了https://mvnrepository.com/ 

注意:
Spring AOP 框架, 在创建新项目的时候,搜索不到。
Spring Boot 项目中,有没有内置 AOP 框架。

这个时候,我们就需要借助 中央仓库了https://mvnrepository.com/ 

 细节拓展: Spring AOP 依赖的版本号标签是可以省略的。
虽然 Spring AOP 没有 作为一个常用框架,导致我们引入框架的时候,需要借助 Maven 中央仓库来引入。
但是!Spring Boot 里面,其实有记录 Spring AOP 的 版本关联信息、
它可根据当前项目的环境,自动引入合适版本的 Spring AOP.


2.2 定义切面(Aspect)

定义方法步骤:



2.3 定义切点(Pointcut)

其中pointcut方法为空方法,其不需要方法体,此方法名就是起到一个“标识”的作用,标识下面的通知方法具体指的是哪个切点。 

切点的语法组成:

 AspectJ支持三种通配符:

  • *:匹配任意字符,只匹配一个元素(包,类,或方法,方法参数)
  • ..:匹配任意字符,可以匹配多个元素,在表示类时,必须和*联合使用
  • +:表示按照类型匹配指定类的所有类,必须跟在类名后面,如com.cad.Car+,表示继承该类的所有子类包括本身;

表达式示例如下:

  • execution(* com.example.demo.UserController. *(..)):匹配UserController类里的所有方法。
  • execution(* com.example.demo.UserController+.*(..)):匹配UserController类的子类包括该类的所有方法
  • execution(* com.example.demo.*.*(..)):匹配com.example.demo包下的所有类的所有方法
  • execution(* com.example.demo..*.*(..)):匹配com.example.demo包下、子孙包下所有类的所有方法
  • execution(* addUser(String,int)):匹配addUser方法,且第一个参数类型是String,第二个参数类型是int

2.4 定义通知(Advice)

切点和通知的关系:

Spring 切面类中,可以在方法上使用以下注解,设置方法为通知方法,在满足条件后会通知本方法进行调用:

  • 前置通知使⽤ @Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。
  • 后置通知使⽤ @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。
  • 返回之后通知使⽤ @AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。
  • 抛异常后通知使⽤ @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。
  • 环绕通知使⽤ @Around:通知包裹了的⽅法(集合中的连接点),在被通知的⽅法收到通知之前和调⽤之后执⾏⾃定义的⾏为。

实现通知方法:在什么时机执行什么方法。

以前置方法为例,演示一下:


三、实例展示(计时器)

我们可以在 其值方法中 加一行代码,记录 开始时间。
然后,再在 后置方法中 记录 结束时间。
最后,两者相减,不就得到了 拦截到的方法的执行时间了嘛!
这样做,真的对吗? 是不对。

这得看情况。

如果是在单线程的环境下(同一时刻,只有一个线程在访问该方法),使用上述方式,没有问题。

但是!
在多线程的情况下,有多个用户访问 会被拦截下来的方法,每一次访问,都会调用 前置方法。
这会导致, 前置方法记录的开始时间,会不停被刷新(覆盖),最终记录的是 最后一个线程访问的时间。
后置方法,也是同样的情况。



也就是说我们最终相减的情况:
哪一次的开始时间 减去 哪一次 结束时间,我们都是无从获知的!
而且,得出非常多,数量取决访问的线程有多少。

那么,问题来了!
前面我不是说: AOP 可以统⼀⽅法执⾏时间的统计嘛。
但是,遇到问题了、
那么,我们该怎么做呢?

.有的人可能会说:这是线程安全问题,加锁呗!
对不起,不行!这就是全局的问题,你加锁也解决不了问题。
但是!我们不是剩一个 环绕通知吗?
解决的办法,就在这里。

下面,我们就来先了解一下 环绕通知。


环绕通知使用@Around:通知包裹了被通知的方法,在被通知的方法通知之前和调用之后执行自定义的行为。

环绕通知@Around:

形象来说:环绕通知,就是把 整个连接点(方法)包裹起来了,那我们就可以“为所欲为”了。

比如说:
我们执行的方法 是在当前通知里面去执行的,所以,我们就可以针对每一个方法去记录开始时间和结束时间。

因为在每一次在执行目标方法(连接点)和 通知 的时候,它们是在一块的。给人的感觉就像是具有了 事务的原子性;

代码实现 

 LoginAop代码 :

package com.example.demo.aop;
 
import com.sun.corba.se.impl.ior.OldJIDLObjectKeyTemplate;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
 
// 切面表示我们要统一出来的问题——比如验证用户是否登录(LoginAop类)
// 切点则是是否进行Aop拦截的规则(哪些页面不需要进行登录验证,哪些需要,这种规则)
// 连接点则是具体到哪些页面需要进行拦截(登录验证)
// 通知则是验证用户是否登录的那个具体方法实现(代码细节)——》前置通知,后置通知
// 验证当前是否登录 的aop实现类
@Component
@Aspect // 表示当前类是一个切面
public class LoginAop {
    // 定义切点
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut() { // 标记切点
    }
    // 前置通知
    @Before("pointcut()") // 参数说明这个前置方法是针对与那个切点的
    public void doBefore() {
        System.out.println("前置通知");
    }
    // 后置通知
    @After("pointcut()")
    public void doAfter() {
        System.out.println("后置通知");
    }
    // 环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        StopWatch stopWatch = new StopWatch();
 
        Object o =  null;
        System.out.println("环绕通知开始执行");
        try {
            stopWatch.start();
            o = joinPoint.proceed();
            stopWatch.stop();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("环绕通知结束执行");
        System.out.println("执行花费的时间: " + stopWatch.getTotalTimeMillis() + "ms");
        return o;
    }
}

总结

 

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

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

相关文章

教学场景下的AI数字人,可视化语音交互

玩了Midjourney,感慨AI太强大了,设计师已哭晕~~ AI数字人 教学场景下的AI数字人,能实现什么? 图:AI数字人 图:AI数字人 个性化学习支持 根据学生的个人需求和学习风格,提供个性化的学习支持和…

(赠书活动第2期)Java生日快乐,“不读此生遗憾”的Java开发必备书单

Java诞生日,推荐Java“此生错过必遗憾”系列书单 Java28岁了,当打之年,并且还会打很多年。 为即将或正在使用Java的你推荐Java“此生错过必遗憾”系列书单。看看你还缺哪本?请补齐。优惠购书链接就在文中,拿好不谢。 …

【权限提升】Linux Kernel 权限提升漏洞 (CVE-2023-32233)

文章目录 前言声明一、漏洞描述二、影响版本三、本地复现四、修复方案 前言 Linux Netfilter 是一个在 Linux 内核中的网络数据包处理框架,也称作 iptables,它可以通过各种规则和过滤器,基于数据包的来源、目标地址、协议类型、端口号等信息…

小程序技术给统一门户的建设带来新的构想

统一门户的发展可以追溯到20世纪90年代初期,当时的企业和组织开始意识到信息技术可以用于整合和管理各种分散的应用程序和服务。随着互联网的普及和Web 2.0技术的兴起,统一门户的发展迅速加速。 在早期,统一门户主要采用定制化开发的方式实现…

数据可视化-Canvas

Canvas Canvas API 主要聚焦于 2D 图形。当然也可以使用<canvas>元素对象的 WebGL API 来绘制 2D 和 3D 图形&#xff0c;可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理。 Canvas非常适合图像密集型的游戏开发&#xff0c;适合频繁重绘许多的对象。能…

opencv膨胀腐蚀

OpenCV 是一个开源的计算机视觉库&#xff0c;它包含了许多图像处理的功能&#xff0c;其中膨胀和腐蚀是两种常用的形态学操作。 膨胀&#xff08;Dilation&#xff09;&#xff1a;膨胀操作是将图像中的高亮区域&#xff08;白色像素&#xff09;扩张&#xff0c;从而填充低亮…

火车票和机票已支持数电票,泛微齐业成提供数电票全流程管理方案

数电票已经成为趋势 01扩大全面数字化的电子发票试点范围 2023年以来&#xff0c;河南、深圳等多省市税务局发布《关于开展全面数字化的电子发票试点工作的公告》&#xff0c;进一步扩大了全面数字化的电子发票试点范围&#xff0c;在政府公告、文件描述中&#xff0c;“数电…

轻松提高SketchUp技能的15个简单技巧

SketchUp一直是设计界有名的3d建模软件之一&#xff0c;其直观的工作工具、开源库和无数的插件使 SketchUp 易于使用。通常&#xff0c;它被用来让孩子们接触建筑。其用户友好的界面使其成为初学者的绝佳应用程序。它包含一系列功能&#xff0c;能够以高效和突出的方式为学生和…

雪花算法工具类介绍

简介 雪花 &#xff08;SnowFlake &#xff09;算法是一种分布式唯一ID生成算法&#xff0c;可以生成全局唯一的ID标识符&#xff0c;就像自然界中雪花一般没有相同的雪花。它的核心思想是将一个64位的整数分成4部分&#xff0c;分别是&#xff1a; 1位标识符&#xff1a;即最…

关于ERP系统,你可能不知道的10件事

谈到ERP系统&#xff0c;大多数人只是考虑ERP日常管理的核心功能&#xff0c;即财务、销售、采购、库存、生产和分销。保持对这些关键领域的控制对任何企业的成功都是不可或缺的。但这些只是冰山一角&#xff0c;如果深入挖掘ERP系统&#xff0c;你可能会惊讶于它的其他功能。以…

vue3 - 【完整源码】实现容器用鼠标拖曳功能,将容器 “限制在指定范围内“ 鼠标拖拽移动并拿到横纵坐标(详细示例源码及注释,一键复制开箱即用)

效果图 在vue3网页项目中,实现将一个容器设置为鼠标可拖动拖曳效果(并限制在边界内不可拖出去),并且拖拽时自动获取横纵坐标以及相关的事件,基础的示例可自定义为任何你想要的效果。 你可以直接下方效果图的示例源代码,配合详细的原理描述及代码注释保证可用!稍微改改就…

SIEM(安全信息与事件管理)的重要性及 Log360 的卓越功能

摘要&#xff1a;随着网络安全威胁的不断增加&#xff0c;企业和组织对于安全信息与事件管理&#xff08;SIEM&#xff09;解决方案的需求日益迫切。本文将重点介绍 SIEM 的重要性&#xff0c;并详细探讨 ManageEngine 公司旗下的 Log360 解决方案所提供的卓越功能和优势。 引…

胶片打印、排版、自助打印(二)

一、DICOM打印的两种类型 灰度图像打印&#xff1a; 彩色图像打印&#xff1a; 通常情况下RGB类型DICOM图像包含如下的内容&#xff1a; (0028,0010)Rows 图像的高度 (0028,0011)Columns 图像的宽度 (0028,0030)Pixel Spacing 图像像素间距&#xff0c;读取Pixel Data的时候…

Niagara——概述

Niagara是最新一代VFX系统&#xff0c;无需程序员的帮助&#xff0c;即可创建丰富多彩的效果&#xff1b;高级用户还可自定义模块modules&#xff1b; 核心组件 SystemsEmittersModulesParameters systems systems是构建效果容器&#xff0c;创建不同类型效果元素以实现整体效果…

Python从多个表格中随机抽取数据加以处理后合并全部数据

本文介绍基于Python语言&#xff0c;针对一个文件夹下大量的Excel表格文件&#xff0c;基于其中每一个文件&#xff0c;随机从其中选取一部分数据&#xff0c;并将全部文件中随机获取的数据合并为一个新的Excel表格文件的方法。 首先&#xff0c;我们来明确一下本文的具体需求。…

免交互expect

免交互 一、expect1、环境安装2、基本命令2.1 脚本解释器2.2 spawn&#xff08;跟踪&#xff09;2.3 expect &#xff08;捕捉&#xff09;2.4 send&#xff08;发送&#xff09;2.5 结束符2.7 exp_continue2.8 send user2.9 接收参数 二、ssh无交互登录到远程服务器1、登录完成…

Android 自定义弹窗 附带搜索过滤功能

项目场景&#xff1a; 前两天要求在项目中添加个小功能&#xff0c;今天正好有时间随手写了一个小demo&#xff0c;过程分享给大家。以后如果有此类需求可直接移植使用。 需求是因为在下拉列表中选择一个项作为数据显示在界面上&#xff0c;但是所有的选项很多&#xff0c;下翻…

软件著作权容易搞吗?

没有代码、材料&#xff0c;只有一个软件名字就能拿证&#xff0c;你说容易不… 当然这是对我们软著一级代理来说&#xff0c;每年申请下证几千个软著。下面说说下证要点给大家避坑。人群覆盖高新企业、大学生、大学老师、互联网公司。 软件著作权想要轻松下证&#xff0c;必…

《微服务实战》 第十六章 Spring cloud stream应用

前言 https://github.com/spring-cloud/spring-cloud-stream-binder-rabbit 官方定义Spring Cloud Stream是一个构建消息驱动微服务的框架。应用程序通过inputs或者outputs来与Spring Cloud Stream中binder对象交互。通过我们配置来binding(绑定),而Spring Cloud Stream的bin…

lwIP更新记06:申请 TCP 控制块(tcp_alloc)

从 lwIP-2.0.0 开始&#xff0c;申请 tcp_pcb 控制块的逻辑发生了变化。 每个 tcp 连接都必须有一个 PCB 控制块 &#xff0c;使用函数 tcp_new() 申请 PCB 控制块。tcp_new 函数代码如下所示&#xff1a; /*** Creates a new TCP protocol control block but doesnt place it…