Spring入门之AOP(包含实例代码)

目录

  • 什么是spring AOP
  • AOP的优势
  • AOP的底层原理
  • AOP的相关术语
  • AOP的应用
    • 切入点表达式
      • 格式
      • 注意问题
    • 通知类型
  • 代码示例
    • 1. 导入Maven项目依赖
    • 2. 准备一个实体类(先定义接口再实现)
    • 3. 定义切面类
    • 4. 准备配置文件
    • 5. 准备测试类
    • 6. 测试结果
      • 6.1 方法正常运行
      • 6.2 方法中出现异常

什么是spring AOP

AOP(Aspect Oriented Programming)又称为面向切面开发,是一种编程范式,是OOP(Object Oriented Programming)的延续,也是Spring框架中函数式编程的一种衍生,利用AOP可以对业务层逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的重用性。AOP采取横向抽取机制,取代传统纵向继承体系。

AOP的优势

  1. 在运行期间,可以不修改源代码对已有的方法进行增强。
  2. 提高了开发效率。
  3. 方便后期维护。

AOP的底层原理

实现方式采用技术
接口JDK动态代理技术
类继承cglib代理技术

AOP的相关术语

名称含义
Joinpoint(连接点)指被拦截到的点(可以用的),在spring中指的是方法。因为Spring只支持方法类型的连接点
Pointcut(切入点)指的是要对哪些Joinpoint进行拦截的定义(要用的)
Advice(通知 | 增强)指拦截到Joinpoint之后所要做的事情,通知分为前置通知后置通知异常通知最终通知环绕通知(切面类要完成的功能)
Target(目标对象)代理的目标对象
Weaving(织入)把通知应用到目标对象来创建新的代理对象的过程
Proxy(代理)一个类被AOP织入增强后,就产生了一个结果
Aspect(切面)是切入点 + 通知的结合

AOP的应用

  • AOP主要应用于对Spring中的方法进行增强。

切入点表达式

格式

  • execution([修饰符] 返回值类型 包名.类名.方法名(参数))
  • 例如:<aop:before method="log1" pointcut="execution(public void com.qcby.service.impl.UserServiceImpl.save())"></aop:before>

注意问题

  • 修饰符可以省略,返回值类型不能省略,不确定时用*来代替,包名、类名、方法名都不能省略,可以使用*来代替或部分代替,参数如果只有一个可以用*代替,如果像代表任意参数用…表示。
  • 因此,比较通用的表达式为:execution(* com.qcby.*.*ServiceImpl.save*(…))(需要注意包的层次)

通知类型

通知类型解释
前置通知目标方法执行前进行增强
后置通知目标方法执行后无论失败与否都进行增强
异常通知目标方法执行失败抛出异常后进行增强
最终通知目标方法执行成功后最后进行增强
环绕通知目标方法执行前后都可以进行增强,目标对象的方法需要手动执行

代码示例

实例代码设置了一个UserService实现类,并对这个类的方法进行增强,具体增强的方法为:通过AOP调用配置好的切面类MyAspect的方法。从而使得在UserService执行自身的方法时,可以完成切面方法的调用。

1. 导入Maven项目依赖

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- 连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><!-- mysql驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version><scope>test</scope></dependency><!--AOP联盟--><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><!--Spring Aspects--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.2.RELEASE</version></dependency><!--aspectj--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version></dependency>
</dependencies>

2. 准备一个实体类(先定义接口再实现)

  • 在实体类的方法中存放一个异常:int aa = 1/0;,用来测试异常通知。
package com.qcby.service;public interface UserService {public void save();
}
package com.qcby.service.impl;import com.qcby.service.UserService;
import org.springframework.stereotype.Service;public class UserServiceImpl implements UserService {public void save() {
//        int aa = 1/0;System.out.println("业务层:Hello World!");}
}

3. 定义切面类

package com.qcby.util;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;public class MyAspect {//自定义切面类 = 切入点(表达式) + 通知(增强代码)//通知public void log1() {System.out.println("我是前置增强方法!");}public void log2() {System.out.println("我是后置增强方法!");}public void log3() {System.out.println("我是异常增强方法!");}public void log4() {System.out.println("我是最终增强方法!");}// 开启环绕通知// 需要传入一个参数 spring提供的一个接口 ProceedingJoinPoint// 这个接口中有个proceed方法,作用是让目标对象的方法调用public void aroundLog(ProceedingJoinPoint point) {try {log1();point.proceed(); //目标对象方法手动调用log4(); //失败就不会调用的最终方法} catch (Throwable e) {log3();e.printStackTrace();} finally {log2(); //无论成功与否都会调用的后置方法}}
}

4. 准备配置文件

<?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
http://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"><!--    ioc bean管理--><bean id="us" class="com.qcby.service.impl.UserServiceImpl"></bean><bean id="myAspect" class="com.qcby.util.MyAspect"></bean><!--    aop配置的增强--><aop:config>
<!--        配置切面 = 配置切入点(表达式) + 通知--><aop:aspect ref="myAspect">
<!--            配置前置通知--><aop:before method="log1" pointcut="execution(* com.qcby.*.*.*ServiceImpl.save*(..))"></aop:before>
<!--            后置通知 无论目标方法执行成功与否--><aop:after method="log2" pointcut="execution(public void com.qcby.service.impl.UserServiceImpl.save())"></aop:after>
<!--            异常通知--><aop:after-throwing method="log3" pointcut="execution(public void com.qcby.service.impl.UserServiceImpl.save())"></aop:after-throwing>
<!--            最终通知 目标方法执行成功之后,最后执行--><aop:after-returning method="log4" pointcut="execution(public void com.qcby.service.impl.UserServiceImpl.save())"></aop:after-returning><!--            配置环绕通知(一个顶四个)--><aop:around method="aroundLog" pointcut="execution(* com.qcby.*.*.*ServiceImpl.save*(..))"/></aop:aspect></aop:config>
</beans>

5. 准备测试类

import com.qcby.service.UserService;
import com.qcby.util.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserServiceTest {@Autowiredprivate UserService userService;@Testpublic void run() {userService.save();}
}

6. 测试结果

6.1 方法正常运行

1

6.2 方法中出现异常

2

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

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

相关文章

同三维TM6-6 有线6级联会议麦克风详情介绍

同三维TM6-6 有线6级联会议麦克风 信息通讯类智能阵列麦克风 有线传输&#xff0c;强抗干扰、可级联、长续航、低延时 6个麦克风级联&#xff0c;通过3.5音频线级联, 可以同时使用3.5mm LINE IN/OUT、USB有线连接PC端&#xff0c;每条音频线是3米&#xff0c;可应用在视频会…

阶跃星辰推出Step-1X:让你的想象力插上翅膀

阶跃星辰 在人工智能快速发展的今天&#xff0c;AI绘画技术正以惊人的速度不断突破创新。就在不久前&#xff0c;阶跃星辰在2024世界人工智能大会上发布的Step-1X图像生成大模型。让我们一起走进Step-1X的世界&#xff0c;看看它如何为我们的想象力插上翅膀。 Step-1X Step-1X …

vue3中ref绑定的节点顺序错乱

问题复现 眨眼睛这个是修正过了的&#xff0c;小友的应该是ref直接绑定navigationTextList对吧&#xff0c; 按正常想法肯定是既然这个数组会动态更新&#xff0c;我只需要index不就能确定是哪个节点啦&#xff0c;倘若只是静态数据应该不会有什么问题&#xff0c; ⚠️但如果出…

湖南省工业废水高氯酸盐排放新标准解析与技术应对策略

随着工业化进程的加快&#xff0c;环境污染问题变得尤为突出。特别是在某些特定行业产生的污染物&#xff0c;如高氯酸盐&#xff0c;因其对环境和人体健康的潜在危害&#xff0c;越来越受到关注。为了解决这一问题&#xff0c;湖南省生态环境厅与省市场监督管理局联合制定了《…

网络层 IV(ARP、DHCP、ICMP)【★★★★★★】

&#xff08;★★&#xff09;代表非常重要的知识点&#xff0c;&#xff08;★&#xff09;代表重要的知识点。 一、地址解析协议&#xff08;ARP&#xff09;&#xff08;★★&#xff09; 在局域网中&#xff0c;由于硬件地址已固化在网卡上的 ROM 中&#xff0c;因此常常将…

PPT图表制作不再难!这款在线PPT软件让办公更简单!

ppt图表怎么制作&#xff1f; 在当下注重视觉呈现的数字化时代&#xff0c;有效的信息传递和数据可视化变得越来越重要。不管是商业演示、学术报告还是项目汇报&#xff0c;一份精心制作的PPT演示文稿&#xff0c;往往能够起到事半功倍的效果。其中&#xff0c;图表作为PPT中不…

C++ ─── List的模拟实现

一&#xff0c; List的模拟实现 List 是一个双向循环链表,由于List的节点不连续&#xff0c;不能用节点指针直接作为迭代器&#xff0c;因此我们要对结点指针封装&#xff0c;来实现迭代器的作用。 迭代器有两种实现方式&#xff0c;具体应根据容器底层数据结构实现&#xff1…

Linux 进程概念 进程状态 fock函数讲解

PID和PPID 我如果想获取自己的PID呢&#xff1f; pid_t getpid(void);头文件:#include<sys/types.h> #include<unistd.h> 返回调用这个函数的进程ID(自己的PID) PID一般会变化 如何获取PPID? pid_t getppid(void);(父ID)头文件:#include<sys/types.h>…

提高 Web 应用程序安全性的标准

开放式 Web 应用程序安全项目 (OWASP) 是一个国际非营利组织&#xff0c;致力于为任何有兴趣提高 Web 应用程序安全性的人提供免费文档、工具、视频和论坛。 OWASP 最初成立为开放式 Web 应用程序安全项目&#xff0c;并于 2004 年注册为非营利性慈善机构&#xff0c;提供有关…

redis学习(011 实战:黑马点评:优惠券秒杀:redis实现全局唯一ID)

黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第48p-第p49的内容 文章目录 全局唯一ID编码 全局唯一ID //String did dao.haveKeyId(“deputybedthing”); 这里的主键并没有…

LeetCode—string练习

415.字符串相加 . - 力扣&#xff08;LeetCode&#xff09; 错误示范&#xff1a; 遇到这种我们第一想法就是将字符串转化成整数&#xff0c;但这种解法无法提交通过&#xff0c;只能支持将小数字互相转化&#xff0c;遇到较长的字符串就没法通过。 class Solution { public…

基于FPGA实现SD NAND FLASH的SPI协议读写

基于FPGA实现SD NAND FLASH的SPI协议读写 在此介绍的是使用FPGA实现SD NAND FLASH的读写操作&#xff0c;以雷龙发展提供的CS创世SD NAND FLASH样品为例&#xff0c;分别讲解电路连接、读写时序与仿真和实验结果。 目录 1 FLASH背景介绍 2 样品申请 3 电路结构与接口协议 …

基于微信小程序在线订餐系统

微信小程序在线订餐系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序在线订餐系统的开发全过程。通过分析微信小程序在线订餐系统管理的不足&#xff0c;创建了一个计算机管理微信小程序在线订…

免费下载Win11 24H2专业版!附详细安装教程

今日&#xff0c;系统之家小编给大家带来2024年最新的Windows11 24H2专业版系统&#xff0c;更新后系统版本号将升至26100.1591。系统基于微软官方最新Windows 11 24H2专业版进行离线制作与优化&#xff0c;确保系统安全无毒&#xff0c;兼容性强&#xff0c;可完美支持新老机型…

解锁高效项目管理:精选软件项目管理工具与技术实战

在当今快节奏的商业环境中&#xff0c;项目管理不仅是确保任务按时完成的手段&#xff0c;更是企业战略规划与执行的核心。面对日益复杂的项目需求和不断变化的市场环境&#xff0c;传统的手工管理方式已难以满足高效协同的要求。此时&#xff0c;项目管理软件作为数字化时代的…

【数据推荐】我国省市县三级的人口受教育状况数据(分年龄\性别\户籍)

人口数据是我们在各项研究中都经常使用的数据。之前我们为大家分享过基于《2020中国人口普查分县资料》整理的全国范围的第七次人口普查人口数据&#xff0c;具体包括如下8个分表&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff1a; 表1&#xff1a;我国省市县三…

只会SQL语句,可以做什么工作?

1、SQL是什么 首先简单介绍一下SQL&#xff08;Structured Query Language&#xff09;&#xff0c;是一种可以进行数据提取、聚合、分析&#xff0c;并对数据库进行构建和修改的编程语言。 相对来说&#xff0c;SQL上手非常容易&#xff0c;因为语法结构比较固定&#xff0c…

iOS分渠道统计不再难,Xinstall帮你轻松搞定

在App推广和运营的过程中&#xff0c;iOS分渠道统计一直是一个令人头疼的问题。如何准确追踪各个渠道的推广效果&#xff1f;如何优化投放策略以提高转化率&#xff1f;这些问题困扰着无数推广者。今天&#xff0c;我们就来聊聊Xinstall这款强大的分渠道统计工具&#xff0c;看…

llama_factory Qlora微调异常 No package metadata was found for The ‘autoawq‘

importlib.metadata.PackageNotFoundError: No package metadata was found for The ‘autoawq’ distribution was not found and is required by this application. To fix: pip install autoawq 其实问题比较简单 直接安装autoawq 即可 但是对应会有版本问题&#xff1a; 查…

什么是阿凡达2.0直播模式?

要了解什么是什么是阿凡达2.0直播模式,首先要了解什么是的阿凡达直播模式。 我们知道真人直播&#xff0c;播不了几个小时&#xff0c;主播就讲累了。且真人主播的价格又贵&#xff0c;以小时计费。所以很多数字人厂商推出了数字人直播。用数字人代替真人直播。在前几年的时候…