当前位置: 首页 > 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;一个是跳转页面传入的参数。打开数据源&…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...