当前位置: 首页 > news >正文

spring实现AOP

文章目录

  • 前言
  • 一、AOP的底层实现原理
  • 二、AOP的两种开发模式
    • 1.使用xml配置文件
      • 1.1 添加AOP依赖
      • 1.2 创建UserService
      • 1.3创建UserServiceImpl
      • 1.4创建通知类
      • 1.5 创建applicationContext.xml(添加aop约束)
      • 1.6 测试
    • 2.使用注解开发
      • 2.1 创建bean.xml文件配置注解方式
      • 2.2 在通知类上使用相关注解
      • 2.3 测试
  • 总结


前言

spring的核心是IOC(控制反转)和AOP(面向切面编程)。AOP面向切面编程是通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。


一、AOP的底层实现原理

此处再解释,详情请看我这篇文章
静态代理和动态代理https://blog.csdn.net/l_zl2021/article/details/127095878

二、AOP的两种开发模式

关于AOP的案例,看我这边篇文章,本文只是记录两种AOP开发方式
AOP初识https://blog.csdn.net/l_zl2021/article/details/127113425

1.使用xml配置文件

1.1 添加AOP依赖

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.9.1</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>compile</scope></dependency></dependencies>

1.2 创建UserService

package com.wmj.service;//目标对象target
public interface UserService {//未增强的方法叫做连接点JoinPoint//已增强的方法叫做切入点PointCutpublic void add();public void delete();
}

1.3创建UserServiceImpl

代码如下(示例):

package com.wmj.service.impl;import com.wmj.service.UserService;public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("添加用户..");//int i = 1/0;}@Overridepublic void delete() {System.out.println("删除用户..");}
}

1.4创建通知类

前置通知(before):目标方法运行之前调用
后置通知(after-returning):在目标方法运行之后调用 (如果出现异常不会调用)
环绕通知(around):在目标方法之前和之后都调用(ProceedingJoinPoint对象 -->> 调用proceed方法)
异常拦截通知(after-throwing):如果出现异常,就会调用
最终通知(after):在目标方法运行之后调用 (无论是否出现 异常都会调用)

package com.wmj.advice;import org.aspectj.lang.ProceedingJoinPoint;//通知类,增强的代码(方法)Advice
public class MyAdvice {public void before(){System.out.println("前置通知,目标对象调用方法前执行");}public void after(){System.out.println("后置通知(最终通知),目标对象调用方法后执行,无论是否发生异常都执行");}public void after_returning(){System.out.println("后置通知,目标对象调用方法后执行,发生异常不执行");}public void after_throwing(){System.out.println("异常通知,发生异常执行");}public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("环绕通知,目标对象调用方法之前");joinPoint.proceed();System.out.println("环绕通知,目标对象调用方法之后");}}

1.5 创建applicationContext.xml(添加aop约束)

<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --><bean id="userService" class="com.wmj.service.impl.UserServiceImpl"></bean><!-- 通知 --><bean id="myAdvice" class="com.wmj.advice.MyAdvice"></bean><!-- aop --><!-- 默认使用JDK动态代理 --><!-- proxy-target-class="true" 使用cglib --><aop:config proxy-target-class="true"><!-- 配置切入点 切入点表达式的写法:execution(表达式)public void com.abyg.service.UserServiceImpl.save() void com.wmj.service.UserServiceImpl.save()  其他修饰符无返回值的save空参方法* com.wmj.service.UserServiceImpl.save()  有或者无返回值的save空参方法* com.wmj.service.UserServiceImpl.*()  有或者无返回值的所有空参方法* com.wmj.service.*ServiceImpl.*(..)  有或者无返回值的所有有参或者空参方法* com.wmj.service..*ServiceImpl.*(..)  一般不用,service包下的子包和孙包以ServiceImpl结尾的类中的方法
--><!-- 切入点 -->
<!--                <aop:pointcut id="pc" expression="execution(public void com.wmj.service.impl.UserServiceImpl.add())"/>--><aop:pointcut id="pc" expression="execution(* com.wmj.service.impl.*ServiceImpl.*(..))"/><!-- 切面 --><aop:aspect ref="myAdvice"><!-- 配置前置通知对应的方法 --><aop:before method="before" pointcut-ref="pc"></aop:before><!-- 配置后置通知(最终通知)对应的方法 --><aop:after method="after" pointcut-ref="pc"></aop:after><!-- 配置后置通知对应的方法,发生异常不执行 --><aop:after-returning method="after_returning" pointcut-ref="pc"></aop:after-returning><!-- 配置异常通知对应的方法,发生异常执行 --><aop:after-throwing method="after_throwing" pointcut-ref="pc"></aop:after-throwing><!-- 配置环绕通知对应的方法 --><aop:around method="around" pointcut-ref="pc"></aop:around></aop:aspect></aop:config></beans>

1.6 测试

package com.wmj.test;import com.wmj.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringTest {@Testpublic void testUserService(){ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService)applicationContext.getBean("userService");userService.add();userService.delete();}}

2.使用注解开发

2.1 创建bean.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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --><!-- 准备工作: 导入aop(约束)命名空间 --><!-- 1.配置目标对象 --><bean id="userService" class="com.wmj.service.impl.UserServiceImpl"></bean><!-- 2.配置通知对象 --><bean id="myAdvice" class="com.wmj.advice.MyAdvice"></bean><!-- 3.开启使用注解完成织入 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>

2.2 在通知类上使用相关注解

@Aspect
//表示该类是一个通知类
//通知类,增强的代码(方法)Advice
public class MyAdvice {//自己设置一个切点,管理重复代码@Pointcut("execution(* com.wmj.service.impl.*ServiceImpl.*(..))")public void pc(){}//前置通知//指定该方法是前置通知,并制定切入点@Before("MyAdvice.pc()")public void before(){System.out.println("前置通知,目标对象调用方法前执行");}//最终通知@After("execution(* com.wmj.service.impl.*ServiceImpl.*(..))")public void after(){System.out.println("后置通知(最终通知),目标对象调用方法后执行,无论是否发生异常都执行");}//后置通知@AfterReturning("execution(* com.wmj.service.impl.*ServiceImpl.*(..))")public void after_returning(){System.out.println("后置通知,目标对象调用方法后执行,发生异常不执行");}//异常通知@AfterThrowing("execution(* com.wmj.service.impl.*ServiceImpl.*(..))")public void after_throwing(){System.out.println("异常通知,发生异常执行");}//环绕通知@Around("execution(* com.wmj.service.impl.*ServiceImpl.*(..))")public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("环绕通知,目标对象调用方法之前");joinPoint.proceed();System.out.println("环绕通知,目标对象调用方法之后");}}

2.3 测试

@Test
public void testUserService(){ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("bean.xml");UserService userService = (UserService)applicationContext.getBean("userService");userService.add();userService.delete();
}

总结

本文记录了两种开发AOP编程的方式

相关文章:

spring实现AOP

文章目录前言一、AOP的底层实现原理二、AOP的两种开发模式1.使用xml配置文件1.1 添加AOP依赖1.2 创建UserService1.3创建UserServiceImpl1.4创建通知类1.5 创建applicationContext.xml&#xff08;添加aop约束&#xff09;1.6 测试2.使用注解开发2.1 创建bean.xml文件配置注解方…...

neovim搭建cpp环境

文章目录Windowns下NeoVim搭建cpp环境NeoVim安装插件vim-plugindentLinevim-airlinectagstagbarcoc.vimWindowns下NeoVim搭建cpp环境 在开发过程中习惯在DIE环境中使用vim作为编辑器&#xff0c;在单独的编辑器也常使用gvim图形化编辑器。最近看到NeoVim的特性及兼容性方面不输…...

SpringBoot AES加密 PKCS7Padding 模式

AES 简介&#xff1a;DES 全称为Data Encryption Standard&#xff0c;即数据加密标准&#xff0c;是一种使用密钥加密的块算法&#xff0c;1977年被美国联邦政府的国家标准局确定为联邦资料处理标准&#xff08;FIPS&#xff09; AES 密码学中的高级加密标准&#xff08;Advan…...

按键输入驱动

目录 一、硬件原理 二、添加设备树 1、创建pinctrl 2、创建节点 3、检查 编译复制 三、修改工程模板​编辑 四、驱动编写 1、添加keyio函数 2、添加调用 3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 6、初始化原始变量 7、打开操作 8、读操作 总体代…...

2023年第七周总周结 | 开学倒数第三周

为什么要做周总结&#xff1f; 1.避免跳相似的坑 2.客观了解上周学习进度并反思&#xff0c;制定可完成的下周规划 一、上周问题解决情况 晚上熬夜导致第二天学习状态不好 这周熬夜一天&#xff0c;晚上帮亲戚修手机到22:30&#xff0c;可能是晚上自己的事什么都没做&#xff…...

Springboot扫描注解类

Springboot扫描注解类的入口在AbstractApplicationContext的refresh中&#xff0c;对启动步骤不太了解的&#xff0c;可参考https://blog.csdn.net/leadseczgw01/article/details/128930925BeanDefinitionRegistryPostProcessor接口有多个实现类&#xff0c;扫描Controller、Se…...

Apache日志分析器

您的Apache HTTP服务器生成的日志数据是信息的宝库。使用这些信息&#xff0c;您可以判断您服务器的使用情况、找出漏洞所在&#xff0c;并设法改进服务器结构和整体性能。审核您的Apache日志可在以下情况派上用场&#xff0c;其中包括&#xff1a;识别和纠正频繁出现的错误以增…...

啪,还敢抛出异常

&#x1f649; 作者简介&#xff1a; 全栈领域新星创作者 &#xff1b;天天被业务折腾得死去活来的同时依然保有对各项技术热忱的追求&#xff0c;把分享变成一种习惯&#xff0c;再小的帆也能远航。 &#x1f3e1; 个人主页&#xff1a;xiezhr的个人主页 前言 去年又重新刷了…...

Apache JMeter 5.5 下载安装以及设置中文教程

Apache JMeter 5.5 下载安装以及设置中文教程JMeter下载Apache JMeter 5.5配置环境变量查看配置JDK配置JMeter环境变量运行JMeter配置中文版一次性永久设置正文JMeter 下载Apache JMeter 5.5 官方网站&#xff1a;Apache JMeter 官网 版本介绍&#xff1a; 版本中一个是Bina…...

string类模拟实现

了解过string常用接口后&#xff0c;接下来的任务就是模拟实现string类。 目录 VS下的string结构 默认成员函数和简单接口 string结构 c_str()、size()、capacity()、clear()、swap() 构造函数 拷贝构造函数 赋值重载 析构函数 访问及遍历 容量操作 reserve resize …...

cadence SPB17.4 S032 - allegro - 保存/载入光绘层定义

文章目录cadence SPB17.4 S032 - allegro - 保存/载入光绘层定义概述保存光绘层在新板子中载入已经保存的相同类型老板子定义好的光绘层定义文件碎碎念ENDcadence SPB17.4 S032 - allegro - 保存/载入光绘层定义 概述 以前布线完成, 准备出板厂文件时, 总是要手工重新建立光绘…...

微服务实战--高级篇:分布式缓存 Redis

分布式缓存 – 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题&#xff1a; 1.Redis持久化 Redis有两种持久化方案&#xff1a; RDB持久化AOF持久化 1.1.RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&#xf…...

【C语言】可变参数列表

本篇博客让我们来认识一下C语言学习过程中往往被忽略的可变参数列表 所谓可变参数&#xff0c;就是一个不限定参数数量的函数&#xff0c;我们可以往里面传入任意个数的参数&#xff0c;以达成某些目的。 关联&#xff1a;C11可变模板参数&#xff1b;本文首发于 慕雪的寒舍 …...

目标检测的旋框框文献学习

这是最近打算看完的文献&#xff0c;一天一篇 接下来将记录一下文献阅读笔记&#xff0c;避免过两天就忘了 RRPN 论文题目&#xff1a;Arbitrary-Oriented Scene Text Detection via Rotation Proposals 论文题目&#xff1a;通过旋转方案进行任意方向的场景文本检测&#x…...

Hive 在工作中的调优总结

总结了一下在以往工作中&#xff0c;对于Hive SQL调优的一些实际应用&#xff0c;是日常积累的一些优化技巧&#xff0c;如有出入&#xff0c;欢迎在评论区留言探讨~ EXPLAIN 查看执行计划 建表优化 分区 分区表基本操作&#xff0c;partitioned二级分区动态分区 分桶 分…...

每天一道大厂SQL题【Day09】充值日志SQL实战

每天一道大厂SQL题【Day09】充值日志SQL实战 大家好&#xff0c;我是Maynor。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深大数据选手&#xff0c;深知SQL重要性&#xff0c;接下来我准备用100天时间&#xff0c;基于大数据岗面试中的经典SQL题&#…...

MATLAB 遗传算法

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…...

探讨 Java 中 valueOf 和 parseInt 的区别

前言 在编程中&#xff0c;遇到类型转换&#xff0c;好像会经常用到 parseInt 和 valueOf&#xff0c;当然这里只拿 Integer 类型进行陈述&#xff0c;其他类型也是雷同的&#xff1b; 想必有读者也跟我一样&#xff0c;经常交叉使用这两个方法&#xff0c;但却不知道这两者到…...

JSON学习笔记

♥课程链接&#xff1a;【狂神说Java】一小时掌握JSON_哔哩哔哩_bilibili配套的当然还要学习ajax不管是前端后端&#xff0c;感觉这部分内容是必须的&#xff0c;不然真的做项目的时候云里雾里。总体json的内容不多&#xff0c;具体就&#xff1a;1. 列表、对象等语法格式2. js…...

家政服务小程序实战教程07-轮播图组件

小程序中首页一般显示轮播图的功能&#xff0c;点击轮播图会跳转到具体的一篇文章或者是产品&#xff0c;本篇我们就介绍一下轮播图功能的开发 01 设计数据源 我们轮播图组件需要两个字段&#xff0c;一个是展示的图片&#xff0c;一个是跳转页面传入的参数。打开数据源&…...

JSON数据高效处理:命令行工具jsoncut的查询、过滤与投影实战

1. 项目概述&#xff1a;一个专为JSON数据“瘦身”的利器在前后端开发、API接口调试、数据迁移或者日志分析的日常工作中&#xff0c;JSON格式的数据几乎无处不在。它结构清晰、易于阅读和解析&#xff0c;是现代数据交换的绝对主力。但随之而来的一个常见痛点就是&#xff1a;…...

孤舟笔记 IO 与网络编程篇六 什么是网络四元组?它是理解TCP连接的关键

文章目录一、先说结论&#xff1a;四元组核心事实二、四元组是什么&#xff1f;三、一个端口能建立多少连接&#xff1f;四、客户端的连接上限五、NAT 和四元组六、四元组在负载均衡中的应用网络四元组 全景回答技巧与点评标准回答加分回答面试官点评个人网站面试官问"一个…...

Python金融数据分析实战:从数据清洗到LLM智能问答机器人构建

1. 项目概述&#xff1a;一个金融数据分析与智能问答的实战项目 最近在整理一些数据分析的实战项目&#xff0c;正好翻到了之前为Forage BCGX GenAI项目做的一个金融分析案例。这个项目麻雀虽小&#xff0c;五脏俱全&#xff0c;它完整地走了一遍从原始数据清洗、指标计算、可视…...

VCF 9.1 新特性:安装器与 Fleet Depot 支持 HTTP 无认证离线软件源

VMware Cloud Foundation(VCF)9.0 推出了统一软件仓库(Software Depot)&#xff0c;支持连接博通在线源或企业内部离线源。但在 9.0 中&#xff0c;离线源默认必须使用 HTTPS 基础认证&#xff0c;即使关闭 HTTPS 也依然需要认证&#xff0c;对纯内网环境很不友好。在 VCF 9.1…...

逆向实战:从异或表到明文存储,我是如何让Eternium的游戏数据‘裸奔’的

逆向工程实战&#xff1a;解密游戏数据存储的核心逻辑 在数字娱乐时代&#xff0c;游戏安全机制与逆向分析技术之间的博弈从未停止。对于技术爱好者而言&#xff0c;理解游戏如何保护其核心数据不仅是一次智力挑战&#xff0c;更是深入了解计算机系统底层运作的绝佳机会。本文将…...

从荧光灯到充电器:剖析MJE13001高压小功率三极管的实战选型与参数验证

1. MJE13001三极管的前世今生 第一次见到MJE13001这颗三极管是在修理一台老式荧光灯电子镇流器时。当时电路板上那颗黑乎乎的小元件已经烧得发黄&#xff0c;但依稀能看到"13001"的标识。拆下来用万用表测量发现CE结已经击穿&#xff0c;换上新的MJE13001后&#xf…...

告别头像上传模糊!用Cropper.js打造完美头像裁剪上传功能(附完整前后端代码)

从零构建高精度头像裁剪系统&#xff1a;Cropper.js全栈实战指南 每次上传头像时&#xff0c;你是否遇到过这样的尴尬——精心选择的图片上传后变得模糊不清&#xff0c;或者被强制拉伸变形&#xff1f;这种糟糕的用户体验在社交平台、企业系统中尤为常见。本文将带你从零构建…...

Git 入门教程:从命令行到 IDE 集成

文章目录Git 入门教程&#xff1a;从命令行到 IDE 集成一、环境准备与初始配置1.1 安装 Git1.2 配置用户身份2.2 查看仓库状态2.3 添加文件到暂存区2.4 提交文件到本地仓库2.5 查看历史版本2.6 版本回退2.7 删除文件三、Git 分支操作&#xff08;多人协作核心&#xff09;3.1 分…...

CDMA功率测量技术与Agilent 8960系统优化

1. CDMA功率测量技术背景与挑战在cdma2000移动通信系统中&#xff0c;精确的功率控制是实现高质量通信的核心技术之一。与GSM等采用固定功率等级的系统不同&#xff0c;CDMA要求移动台(MS)能够在80dB动态范围内精确调整发射功率。这种需求源于CDMA系统的自干扰特性——所有用户…...

Watercolor风格在MJ中被严重低估的3个底层能力:纸基模拟、颜料扩散建模、干湿叠加逻辑(Adobe资深插画师联合验证)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Watercolor风格在MJ中被严重低估的3个底层能力&#xff1a;纸基模拟、颜料扩散建模、干湿叠加逻辑&#xff08;Adobe资深插画师联合验证&#xff09; 纸基模拟&#xff1a;不只是纹理&#xff0c;而是…...