spring boot学习第十四篇:使用AOP编程

news2024/12/23 4:31:25

一、基本介绍

1,什么是 AOP

(1)AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

(2)利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

一个 AOP 的使用场景:
    假设一个已经上线的系统运行出现问题,有时运行得很慢。为了检测出是哪个环节出现了问题,就需要监控每一个方法的执行时间,再根据执行时间进行分析判断。
    由于整个系统里的方法数量十分庞大,如果一个个方法去修改工作量将会十分巨大,而且这些监控方法在分析完毕后还需要移除掉,所以这种方式并不合适。
    如果能够在系统运行过程中动态添加代码,就能很好地解决这个需求。这种在系统运行时动态添加代码的方式称为面向切面编程(AOP)

2,AOP 相关概念介绍

  • Joinpoint(连接点):类里面可以被增强的方法即为连接点。例如,想要修改哪个方法的功能,那么该方法就是一个链接点。
  • Target(目标对象):要增强的类成为 Target。
  • Pointcut(切入点):对 Jointpoint 进行拦截的定义即为切入点。例如,拦截所有以 insert 开始的方法,这个定义即为切入点。
  • Advice(通知):拦截到 Jointpoint 之后要做的事情就是通知。通知分为前置通知、后置通知、异常通知、最终通知和环绕通知。例如,前面说到的打印日志监控就是通知。
  • Aspect(切面):即 Pointcut 和 Advice 的结合。

3,安装配置

    Spring Boot 在 Spring 的基础上对 AOP 的配置提供了自动化配置解决方案,我们只需要修改 pom.xml 文件,添加 spring-boot-starter-aop 依赖即可。

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

二、使用样例

1,创建 Service

首先创建一个 UserService(假设在 com.hmblogs.backend.service),内容如下:

package com.hmblogs.backend.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public String getUserById(Integer id) {
        System.out.println("getUserById(" + id + ")...");
        // 等待2秒
        try {
            Thread.sleep(2000);
        }
        catch(InterruptedException e) {
            e.printStackTrace();
        }
        return "hangge";
    }
}

2,创建切面

接着定义一个切面类,代码如下:

注解说明:
(1)@Aspect 注解:表明这是一个切面类。
(2)@Pointcut 注解:表明这是一个切入点。

  • execution 中的第一个 * 表示方法返回任意值
  • 第二个 * 表示 service 包下的任意类
  • 第三个 * 表示类中的任意方法,括号中的两个点表示方法参数任意,即这里描述的切入点为 service 包下所有类中的所有方法。

(3)@Before 注解:表示这是一个前置通知,该方法在目标方法之前执行。

  • 通过 JoinPoint 参数可以获取目标方法的方法名、修饰符等信息。

(4)@After 注解:表示这是一个后置通知,该方法在目标执行之后执行。
(5)@AfterReturning 注解:表示这是一个返回通知,在该方法中可以获取目标方法的返回值。

  • returning 参数是指返回值的变量名,对应方法的参数。
  • 注意:本样例在方法参数中定义 result 的类型为 Object,表示目标方法的返回值可以是任意类型。若 result 参数的类型为 Long,则该方法只能处理目标方法返回值为 Long 的情况。

(6)@AfterThrowing 注解:表示这是一个异常通知,即当目标方法发生异常,该方法会被调用。

  • 样例中设置的异常类型为 Exception 表示所有的异常都会进入该方法中执行。
  • 若异常类型为 ArithmeticException 则表示只有目标方法抛出的 ArithmeticException 异常才会进入该方法的处理。

(7) @Around 注解:表示这是一个环绕通知。环绕通知是所有通知里功能最为强大的通知,可以实现前置通知、后置通知、异常通知以及返回通知的功能。

  • 目标方法进入环绕通知后,通过调用 ProceedingJointPoint 对象的 proceed 方法使目标方法继续执行,开发者可以再次修改目标方法的执行参数、返回值,并且可以在此目标方法的异常。
package com.hmblogs.backend.util;

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

@Aspect
@Component
public class LogAspect {
    // 定义一个切入点
    @Pointcut("execution(* com.hmblogs.backend.service.*.*(..))")
    public void pc1(){

    }

    // 前置通知
    @Before(value = "pc1()")
    public void before(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法开始执行...");
    }

    // 后置通知
    @After(value = "pc1()")
    public void after(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法执行结束...");
    }

    // 返回通知
    @AfterReturning(value = "pc1()", returning = "result")
    public void afterReturning(JoinPoint jp, Object result) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法返回值为:" + result);
    }

    // 异常通知
    @AfterThrowing(value = "pc1()", throwing = "e")
    public void afterThrowing(JoinPoint jp, Exception e) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法抛异常了,异常是:" + e.getMessage());
    }

    // 环绕通知
    @Around("pc1()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        String name = pjp.getSignature().getName();
        // 统计方法执行时间
        long start = System.currentTimeMillis();
        Object result = pjp.proceed();
        long end = System.currentTimeMillis();
        System.out.println(name + "方法执行时间为:" + (end - start) + " ms");
        return result;
    }
}

3,创建 Controller

配置完成后,接下来在 Controller 中创建接口调用 UserService 中的方法。

package com.hmblogs.backend.controller;

import com.hmblogs.backend.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Autowired
    UserService userService;

    @GetMapping("/test")
    public String test(Integer id) {
        return userService.getUserById(id);
    }
}

4,运行样例

(1)使用浏览器访问如下地址:

  • http://localhost:8081/test?id=11

(2)查看控制台信息,可以发现 LogAspect 中的代码动态地嵌入目标方法中执行了。


 

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

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

相关文章

排水管网信息化平台:科技赋能,助力城市水环境管理升级

排水管网承担着城市污水、雨水的收集与排出的双重任务&#xff0c;是城市重要的基础设施。城市化率的不断提高&#xff0c;对城市基础设施的性能也提出了考验。 排水管网存在窨井监测设备不足、管段淤积、无序监管、污水超标排放等问题突出&#xff0c;导致部分污水直排受纳水…

Springboot笔记-05

1.Springboot的热部署 spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署&#xff0c;提高开发者的开发效率&#xff0c;无需手动重启Spring Boot应用。 在pom文件加入依赖 <dependency> <groupId>org.springframework.boot…

像uniapp image标签一样对图片进行缩放和裁剪

像uniapp image标签一样对图片进行缩放和裁剪 0 前言提示1 实现1.1 不保持纵横比缩放图片&#xff0c;使图片的宽高完全拉伸至填满 image 元素1.2 保持纵横比缩放图片&#xff0c;使图片的长边能完全显示出来。也就是说&#xff0c;可以完整地将图片显示出来。1.3 保持纵横比缩…

NCV7428D15R2G中文资料PDF数据手册参数引脚图图片价格概述参数芯片特性原理

产品概述&#xff1a; NCV7428 是一款系统基础芯片 (SBC)&#xff0c;集成了汽车电子控制单元 (ECU) 中常见的功能。NCV7428 为应用微控制器和其他负载提供低电压电源并对其进行监控&#xff0c;包括了一个 LIN 收发器。 产品特性&#xff1a; 控制逻辑3.3 V或5 V VOUT电源&…

JavaScript 使用 Promise 实现 sleep 休眠

以下为代码实现&#xff0c;该代码实现了每隔1秒打印一次当前时间&#xff0c;总共打印5次的功能 for(let i 1; i < 5; i){console.log(new Date().toString())await new Promise(resolve>setTimeout(resolve,1000)) }实现休眠的核心代码为: await new Promise(resolv…

挖掘网络宝藏:利用Scala和Fetch库下载Facebook网页内容

介绍 在数据驱动的世界里&#xff0c;网络爬虫技术是获取和分析网络信息的重要工具。本文将探讨如何使用Scala语言和Fetch库来下载Facebook网页内容。我们还将讨论如何通过代理IP技术绕过网络限制&#xff0c;以爬虫代理服务为例。 技术分析 Scala是一种多范式编程语言&…

在windows上安装Jenkins

jenkins安装 下载jenkins 官网&#xff1a;Jenkins download and deployment 官方文档说明&#xff1a;Jenkins User Documentation 安装jenkins1.点击下载好的安装包&#xff0c;点击Next 2.选择一个安装路径 如果系统是windows家庭版打不开策略就创建一个txt文件&#xff0c…

node.js常用的命令

Node.js 是一个用于执行 JavaScript 代码的运行时环境。以下命令是 Node.js 开发中常用的命令&#xff0c;可以帮助你进行包管理、项目配置和代码执行等操作。 node -v&#xff1a;检查 Node.js 的版本。npm -v&#xff1a;检查 npm&#xff08;Node.js 包管理器&#xff09;的…

企业工商年报注册注销商标注册异常处理小程序开源版开发

企业工商年报注册注销商标注册异常处理小程序开源版开发 1、独立业务模型包括&#xff1a;企业工商年报、企业工商登记注册、企业注销登记、企业异常处理。 2、通用业务模型适合各种业务&#xff0c;比如&#xff1a;商标注册代理、财务会计服务、企业版权登记登。 当然&…

2024 用CleanMyMac X为您的MAC清理提速吧

CleanMyMac X 是由 MacPaw 公司开发的一款针对 macOS 操作系统的电脑清理工具。它可以帮助用户清理电脑中的垃圾文件、卸载不需要的软件、优化电脑性能等。它的界面简洁明了&#xff0c;操作简单易懂&#xff0c;非常适合普通用户使用。 链接: https://pan.baidu.com/s/1_TFnrI…

Zookeeper(六)Zokeeper 使用场景案例

目录 一 数据发布/订阅1.1 配置变更1.2 代码实现1.3 启动测试 二 负载均衡2.1 实现2.2 代码2.3 启动测试 三 分布式ID3.1 代码实现3.2 效果 四 服务器集群监控五 分布式锁2.1 排他锁2.2 共享锁 官网&#xff1a;Apache ZooKeeper 一 数据发布/订阅 数据发布/订阅(Publish/Sub…

怎样修改grafana的Loading picture和加载的文本

登录装了grafana的linux机器 command “sudo vi /usr/share/grafana/public/views/index.html”&#xff0c;编辑配置文件。 找到.preloader__logo更改background-image. 这里可以是个url也可以是个路径。 如果想要更改加载的文字.可以更改 的内容 改完:wq保存以后退出&…

从键盘到屏幕:C语言中输入输出探秘

在编程中&#xff0c;输入和输出是我们与计算机交流的关键。无论是键盘输入还是屏幕输出&#xff0c;它们贯穿了我们每一行代码的编写。本文将带你深入探索C语言中输入输出的精彩世界&#xff0c;解锁其中的奥秘&#xff0c;助你轻松驾驭键盘和屏幕&#xff01;&#xff08;最后…

C++ List底层实现

文章目录 前言成员变量成员函数迭代器self& operator()前置self operator(int)后置self operator--()前置--self operator--(int)后置--bool operator!(const self & tmp)判断是否相等T* operator*() 解引用操作 list()初始化iterator begin()iterator end()const_iter…

年度告警分类统计

1、打开前端Vue项目kongguan_web&#xff0c;完成前端src/components/echart/YearWarningChart.vue页面设计 在YearWarningChart.vue页面添加div设计 <template><div class"home"><div style"margin: 0px auto;height: 100%"><div …

seleniumUI自动化实例(CSDN发布文章)

1.CSDN登陆成功后&#xff0c;点击发布 源码&#xff1a; #点击首页中的发布按钮 CSDNconf.driver.find_element(By.LINK_TEXT,"发布").click() time.sleep(15) 2.输入标题 #输入文章标题&#xff0c;标题格式“selenium UI自动化测试实例今天的日期” CSDNconf.d…

「数据分析」之零基础入门数据挖掘

摘要&#xff1a;对于数据挖掘项目&#xff0c;本文将学习应该从哪些角度分析数据&#xff1f;如何对数据进行整体把握&#xff0c;如何处理异常值与缺失值&#xff0c;从哪些维度进行特征及预测值分析&#xff1f; 探索性数据分析&#xff08;Exploratory Data Analysis&#…

期刊如何反击一波可疑图像

出版商正在部署基于人工智能的工具来检测可疑图像&#xff0c;但生成式人工智能威胁着他们的努力。 期刊正在努力检测用于分析蛋白质和DNA的凝胶的操纵图像。图片来源&#xff1a;Shutterstock 似乎每个月都会有一系列针对研究人员的新高调指控&#xff0c;这些研究人员的论文…

正则表达式具体用法大全

# 正则表达式&#xff1a; ## 单字符匹配&#xff1a; python # 匹配某个字符串&#xff1a; # text "abc" # ret re.match(b,text) # print(ret.group()) # 点&#xff08;.&#xff09;&#xff1a;匹配任意的字符(除了\n)&#xff1a; # text "\nabc&quo…

《论文阅读》带边界调整的联合约束学习用于情感原因对提取 ACL 2023

《论文阅读》带边界调整的联合约束学习用于情感原因对提取 前言简介Clause EncoderJoint Constrained LearningBoundary Adjusting损失函数前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦~ 无抄袭,无复制,纯手工敲击键盘~ 今天为大家带来的是《Joint Cons…