Spring AOP[详解]

news2025/7/16 7:10:48

一.需求引入

在开发过程中,总会有一些功能与业务逻辑代码耦合度不强(例如保存日志,提交事务,权限验证,异常处理),我们可以将这些代码提取到一个工具类中,需要使用时在调用工具类来实现. ​ 但是这样也会有弊端,那就是我们的代码已经开发完毕,后期如果需要增加公共功能就需要更改原来的代码,有时工作量很大,非常繁杂. ​ 那么我们能不能在不修改原有代码的情况下,也能添加公共功能? AOP面向切面编程技术应用而生

二.AOP概述

AOP的全称为Aspect-Orientend-Programming,即面向切面编程.它是面向对象编程(OOP)的一种补充. 为了解决上述问题,AOP思想随之产生,AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程编译或运行时,再将这些提取出来的代码应用到需要执行的地方.这种采用横向抽取机制的方式,采用传统的OOP思想是无法办到的,因为OOP只能实现父子关系的纵向重用.

AOP核心原理:

使用动态代理的方式在方法执行前后或者出现异常时加入相关的逻辑.

注:

  • 虽然AOP是一种新的编程思想,但是却不是OOP的替代品,是对OOP的延伸和补充.

  • AOP也不是Spring所特有的思想,很多框架都引入了AOP思想

三.Spring AOP基本术语

  • 连接点(JoinPoint): 程序执行的某个特定位置,如某个方法调用前,调用后,方法抛出异常后,这些代码中的特定点称为连接点.可以简单理解为可以被增强的方法

  • 切入点(pointcut): 类中有很多方法可以被增强,但比如实际只有add(),update()方法被增强了,那么add,update方法就被称为切入点,可以简单理解为实际被增强的方法

  • 通知(Advice): 通知是指一个特定的切面在切入点要做的事情,通知分为方法执行前通知,方法执行后通知,环绕通知等.可以简单理解为实际增强的功能

  • 切面(Aspect): 把通知添加到切入点的过程称为切面

  • 目标(Target): 代理的目标对象(连接点,切入点,所在的类实际的执行者)

  • 代理(Proxy): 向目标对象应用通知时创建的代理对象

四.Spring AOP实现

AspectJ 是一个基于 Java 语言的 AOP 框架,它提供了强大的 AOP 功能,且其实现方式更为简捷,使用更为方便, 而且还支持注解式开发。所以,Spring 又将 AspectJ 的对于 AOP 的实现也引入到了自己的框架中。

1.导入spring aspect jar包

其在Maven仓库中的项目坐标如下:

 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-aspects</artifactId>
     <version>5.2.2.RELEASE</version>
 </dependency>

2.编写业务功能及需要增强的功能

此处我们以保存管理员之前增加日志功能为例

2.1原有业务功能:

package com.ffyc.springdemo.dao;
 ​
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Repository;
 ​
 @Repository
 public class AdminDao {
 ​
     @Autowired
     JdbcTemplate jdbcTemplate;
 ​
     public void saveAdmin(){
         System.out.println("保存管理员");
     }
 ​
     public void update(){
         System.out.println("修改管理员");
 ​
     }
 }
 ​

2.2保存日志功能

 package com.ffyc.springdemo.util;
 ​
 public class CommonUtil {
 ​
     public void saveLog(){
         System.out.println("保存日志");
     }
 }

3.1基于 aspectj 的 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
         https://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">
 ​
     <!--开启Spring注解扫描-->
     <context:component-scan base-package="com.ffyc.springdemo"></context:component-scan>
 ​
     <!--导入数据库连接拦截-->
     <import resource="db.xml"></import>
 ​
     <!--让spring管理要增强功能的类-->
     <bean id="commonUtil" class="com.ffyc.springdemo.util.CommonUtil"></bean>
     <!--aop配置-->
     <aop:config>
         <!--配置切入点-->
         <aop:pointcut id="saveAdmin" expression="execution(* com.ffyc.springdemo.dao.AdminDao.saveAdmin(..))"/>
         <!-- 配置通知和切入点 -->
         <aop:aspect ref="commonUtil">
             <aop:before method="saveLog" pointcut-ref="saveAdmin"></aop:before>
         </aop:aspect>
     </aop:config>
 </beans>
 ​

注:

AspectJ中有五种通知类型:

  • 前置通知(Before Advice): 在连接点之前执行的通知(我们上述栗子就使用的是前置通知)

  • 后置通知(After Advice): 在连接点之后执行的通知

  • 环绕通知(Around Advice): 包围一个连接点的通知,这是最强大的通知类型.环绕通知可以在方法调用前后完成自定义的行为.它也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行.

  • 返回后通知(AfterReturning Advice): 在连接点正常完成后执行的通知

  • 抛出异常后通知(After Throwing Advice): 在方法抛出异常退出时执行的通知

3.2基于注解方式的实现

基于注解方式的实现与基于xml文件实现的方式相同,都是基于AspectJ的实现,因此也有五种通知类型,在此我们只示例部分即可.

1.启动AspectJ 支持:

我们需要将此配置加入spring.xml文件中,以启动AspectJ支持

 <aop:aspectj-autoproxy />

2.在业务类上添加注解: @Component @Aspect

 package com.ffyc.springdemo.util;
 ​
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 ​
 @Component
 @Aspect
 public class CommonUtil {
 ​
 }

3.在所需方法上添加注解:

package com.ffyc.springdemo.util;
 ​
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.AfterThrowing;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 ​
 @Component
 @Aspect
 public class CommonUtil {
 ​
 ​
     @Before("execution(* com.ffyc.springdemo.dao.AdminDao.*(..))")
     public void saveLog(){
         System.out.println("保存日志");
     }
 ​
     @AfterThrowing(value = "execution(* com.ffyc.springdemo.dao.AdminDao.*(..))",throwing = "e")
     public void exception(Throwable e){
         System.out.println("系统忙"+e.getMessage());
     }
 }
 ​

注:

  • 注解通知中的“execution(* com.ffyc.springdemo.dao.* .*(..))”称为切入点表达式 execution()是最常用的切点表达式,可分为5个部分:

    • execution为表达式主体

    • 第一个*为返回值类型, * 表示可返回所有类型

    • com.ffyc.springdemo.dao.AdminDao为包名,表示需要拦截的包名

    • 第二个*为类名, * 表示包中所有类

    • *(..)最后的 * 表示方法名, * 表示类中的所有方法;括号中表示方法的参数, .. 表示任意参数

4.结果分析:

我们在上述saveLog()方法上添加了前置通知,并选择为AdminDao中所有方法都执行,因此在保存管理员和修改管理员之前都执行了保存日志操作.

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

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

相关文章

Pinpoint--基础--03--安装部署

Pinpoint–基础–03–安装部署 前提 使用hd用户登陆 完成基础环境搭建https://blog.csdn.net/zhou920786312/article/details/118212302代码位置 https://gitee.com/DanShenGuiZu/learnDemo/tree/master/pinpoint-learn/demo11、安装环境准备 1.1、jdk1.8 基础环境搭建 包含…

一文搞懂MySQL表字段类型长度的含义

不知道大家第一眼看标题的时候有没有理解&#xff0c;什么是“字段类型长度”&#xff0c;这里我来解释下&#xff0c;就比如我们在MySQL建表的时候&#xff0c;比如下面这个建表语句&#xff1a; CREATE TABLE user (id int(10) DEFAULT NULL,name varchar(50) DEFAULT NULL,…

linux系统离线安装docker(分步法一键法)

1 前言 在有的项目场景中&#xff0c;服务器是不允许连接外网的。此时若想在服务器上安装部署docker容器&#xff0c;就不能采用在线方式了&#xff0c;不过可以采取离线方式进行安装。下面我们就一起看看离线安装的两种办法。 一种是分步安装法&#xff0c;一种是一键安装法…

Python冷知识:如何找出新版本增加或删除了哪些标准库?

“内置电池”是 Python 最为显著的特性之一&#xff0c;它提供了 200 多个开箱即用的标准库。但是&#xff0c;历经了 30 多年的发展&#xff0c;很多标准库已经成为了不得不舍弃的历史包袱&#xff0c;因为它们正在“漏电”&#xff01; 好消息是&#xff0c;Python 正在进行…

Pinpoint--基础--02--架构设计

Pinpoint–基础–02–架构设计 1、整体架构 1.1、Pinpoint Collector 数据收集模块&#xff0c;接收Agent发送过来的监控数据&#xff0c;并存储到HBase部署在 Web 容器上 1.2、Pinpoint Web 监控展示模块&#xff0c;展示系统调用关系、调用详情、应用状态等&#xff0c;并…

CleanMyMac磁盘空间内存瘦身清理软件使用教程

许多用着Mac系统电脑的朋友们总是卸载不干净电脑垃圾软件&#xff0c;想要把垃圾软件卸载干净&#xff0c;可以尝试使用苹果电脑清理软件CleanMyMac。 经典的电脑深度清理软件——CleanMyMac。由于苹果电脑硬盘售价高昂&#xff0c;且不可以自行安装内存&#xff0c;很多苹果用…

代码随想录day60|结束亦是开始|84.柱状图中最大的矩形|总结

代码随想录day60 来了老弟 84.柱状图中最大的矩形 思路 本题和42. 接雨水是遥相呼应的两道题目&#xff0c;建议都要仔细做一做&#xff0c;原理上有很多相同的地方&#xff0c;但细节上又有差异&#xff0c;更可以加深对单调栈的理解&#xff01;42. 接雨水 其实这两道题目先…

java 分布式游戏服务器框架,集群游戏服务器框架,游戏服务器网关框架 ioGame 网络游戏服务器框架

网络游戏框架简介 ioGame 是一个由 java 语言编写的网络游戏服务器框架。支持 websocket、tcp &#xff0c;适用于全球同服、回合制游戏、策略游戏、即时战斗等游戏服务器的开发。具有高性能、稳定、易用易扩展、超好编程体验等特点。可做为 H5、手游、端游的 java 游戏服务器…

Intel关NUMA的内存编址

最近在做某国产化平台相关的适配, 不管NUMA的性能和实现方式都和Intel有较大不同, 作为比较对象, 理解Intel的NUMA实现是很有必要的. 虽然从软件角度, 打开NUMA会带来额外的复杂度, 但是从硬件角度, 关闭NUMA其实更复杂, 本文尝试分析关闭NUMA时Intel平台的内存编址. Memory I…

java+springboot基于性别网上学习特征问卷调查及可视化系统

基于JSP技术、SSM框架、B/S机构、Mysql数据库设计并实现了性别网上学习特征及可视化。系统主要包括个人中心、用户管理、调查问卷管理、用户答卷管理、专家建议管理、学习攻略管理、我的收藏管理、爬虫管理、系统管理等功能模块。 (1)绪论 网站的开发背景&#xff0c;意义和系…

栈和队列(带图,有手就废)

文章目录1.栈1.1栈的概念与结构1.2栈的声明1.3动态栈的实现1.3.1初始化栈1.3.2入栈1.3.3出栈1.3.4获取栈顶元素1.3.5获取栈中元素个数1.3.6判断栈是否为空1.3.7销毁栈1.4栈的总结2.队列2.1队列的概念与结构2.2队列的声明2.3队列的实现2.3.1初始化队列2.3.2入队2.3.3出队2.3.4获…

BUUCTF web之WarmUp 源代码详解

目录 前言 PHP代码分析 关于../ 前言 访问除了一张滑稽图&#xff0c;就没其他的了 查看源码&#xff0c;有一个注释了的 source.php&#xff0c;可以尝试直接访问一下。同时进行目录扫描 访问source.php&#xff0c;里面包含php代码&#xff0c;题目说了是php代码审计&…

知识经验分享——YOLOv5-6.0训练出错及解决方法(RuntimeError)

>>>深度学习Tricks&#xff0c;第一时间送达<<< 目录 一、问题bug 二、解决方法 步骤1&#xff1a;打开utils/loss.py文件 步骤2&#xff1a;找到 for i in range(self.nl) 函数&#xff08;CtrlF&#xff09;&#xff0c;作以下替换&#xff1a; 步骤3…

VMware创建Win10操作系统虚拟机

VMware创建Win10操作系统虚拟机1. 安装VMware162. 下载Win10镜像3. 创建虚拟机4. 安装Win105. 安装VMware Tools工具1. 安装VMware16 迅雷云链接&#xff1a;https://pan.xunlei.com/s/VNH9mkbxLqnyB_F_g0h73C_TA1?pwdsdi4# 2. 下载Win10镜像 百度云链接&#xff1a;https:…

优雅的实现符合开闭原则的流水日志抽取demo

如何做出一个标准化记录流水日志(Demo) 昨天晚上 在b站刷到了 极海Channel 海哥的视频 也想去跟着实现一个,作为学习的demo,主要学习思路 可能存在的问题: 可能每一个需要收集的类里取参数的字段可能是不一样的如何去处理如何可以让他更好的作用于新的业务代码上 项目代码日志…

c++STL库

什么是STLSTL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。STL的版本原始版本Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本&#xff0c…

阿里首次公开企业级 SpringBoot 实战进阶笔记

Spring Boot 的重要性不需要我多说了吧&#xff0c;Java程序员们应该都懂&#xff0c;不仅面试会被提问&#xff0c;工作中也非常需要spring boot 不知道大家是如何学习Spring Boot的&#xff0c;据我所知&#xff0c;很多开发者会试着在网上找一些开源项目&#xff0c;通过阅…

马上2023了,云原生架构还不懂?阿里云原生架构笔记带你完全拿下

前言 软件架构发展至今&#xff0c;经历了从单体架构、垂直架构、SOA 架构到现在的以微服务、服务网格等云原生技术为主的演变过程&#xff0c;云原生技术发展势不可挡&#xff0c;老生常谈的“云原生”将依然会是未来的热门话题。而且随着数字化转型加速&#xff0c;企业对于…

Spring Data JPA之自动创建数据库表

Spring Data JPA之自动创建数据库表前言Spring Data JPA demo实现步骤导入依赖创建实体类编辑application.yml文件配置数据库连接和jpa配置运行测试总结如果博主的文章对您有所帮助&#xff0c;可以评论、点赞、收藏&#xff0c;支持一下博主!!!前言 由于在项目中使用到了Spri…

C++11中篇

文章目录1. 右值引用和移动语义1.1 左值引用和右值引用1.2 左值引用与右值引用比较1.3 右值引用使用场景和意义1.5 完美转发2. default 和delete1. 右值引用和移动语义 1.1 左值引用和右值引用 传统的C语法中就有引用的语法&#xff0c;而C11中新增了的右值引用语法特性&#…