Spring Boot AOP的使用
简单来说讲,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
AOP几个术语
- 切面
切面是通知和切点的结合。通知和切点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能。比如事务管理是一个切面,权限管理也是一个切面。
- 通知
通知定义了切面是什么以及何时使用。
Spring切面中定义了5个通知类型:
* 前置通知:在目标方法调用之前执行
* 后置通知:在目标方法调用之后执行
* 返回通知:在目标方法成功执行之后执行
* 异常通知:在目标方法抛出异常之后执行
* 环绕通知:通知包裹了方法,可同时定义前置和后置通知。
- 切点
切点定义了在何处工作,也就是在那个方法应用通知。
- 连接点
连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为
- 引入
引入让一个切面可以声明被通知的对象实现了任何他们没有真正实现的额外接口,而且为这些对象提供接口的实现。
引入允许我们向现有的类添加新方法或属性。这个新方法和实例变量就可以被引入到现有的类中,从而可以再无需修改这些现有的类的情况下,让它们具有新的行为和状态。
- 织入
织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以织入。
AOP Demo
下面是一个小Demo
引入Maven依赖
<!--引入SpringBoot的Web模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入AOP依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
一个简单的Controller
package com.example.demo.aop;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc: 核心业务模块
* @author: CSH
**/
@RestController
@RequestMapping("/aopController")
public class AopController {
@RequestMapping(value = "/Curry")
public void Curry(){
System.out.println("库里上场打球了!!");
}
@RequestMapping(value = "/Harden")
public void Harden(){
System.out.println("哈登上场打球了!!");
}
@RequestMapping(value = "/Antetokounmpo")
public void Antetokounmpo(){
System.out.println("字母哥上场打球了!!");
}
@RequestMapping(value = "/Jokic")
public void Jokic(){
System.out.println("约基奇上场打球了!!");
}
@RequestMapping(value = "/Durant/{point}")
public void Durant(@PathVariable("point") int point){
System.out.println("杜兰特上场打球了!!");
}
}
定义切面类
在类上添加@Aspect 和@Component 注解即可将一个类定义为切面类。
@Aspect 注解 使之成为切面类
@Component 注解 把切面类加入到IOC容器中
package com.example.demo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @desc: 经纪人切面
* @author: CSH
**/
@Aspect
@Component
public class BrokerAspect {
/**
* 定义切入点,切入点为com.example.demo.aop.AopController中的所有函数
*通过@Pointcut注解声明频繁使用的切点表达式
*/
@Pointcut("execution(public * com.example.demo.aop.AopController.*(..)))")
public void BrokerAspect(){
}
/**
* @description 在连接点执行之前执行的通知
*/
@Before("BrokerAspect()")
public void doBeforeGame(){
System.out.println("经纪人正在处理球星赛前事务!");
}
/**
* @description 在连接点执行之后执行的通知(返回通知和异常通知的异常)
*/
@After("BrokerAspect()")
public void doAfterGame(){
System.out.println("经纪人为球星表现疯狂鼓掌!");
}
/**
* @description 在连接点执行之后执行的通知(返回通知)
*/
@AfterReturning("BrokerAspect()")
public void doAfterReturningGame(){
System.out.println("返回通知:经纪人为球星表现疯狂鼓掌!");
}
/**
* @description 在连接点执行之后执行的通知(异常通知)
*/
@AfterThrowing("BrokerAspect()")
public void doAfterThrowingGame(){
System.out.println("异常通知:球迷要求退票!");
}
}
上面前置通知后置通知等都需要配置到定义的切点上。可以定义好多个切点@Pointcut。
调用服务
调用http://localhost:8080/aopController/Harden,输出结果:

切点表达式

环绕通知
Spring中使用次数最多的是环绕通知,
/**
* @description 使用环绕通知
*/
@Around("BrokerAspect()")
public void doAroundGame(ProceedingJoinPoint pjp) throws Throwable {
try{
System.out.println("经纪人正在处理球星赛前事务!");
pjp.proceed();
System.out.println("返回通知:经纪人为球星表现疯狂鼓掌!");
}
catch(Throwable e){
System.out.println("异常通知:球迷要求退票!");
}
}
环绕通知接收一个ProceedingJoinPoint参数,可以用他来调用被通知方法,当调用proceed()方法之前,环绕通知可以做任何操作,控制权在环绕通知中,在调用proceed()方法之后,控制权返回被通知方法,被通知方法执行结束之后,控制权返回到环绕通知手中,继续执行后续操作。如果不调用proceed()方法,则被通知方法会被一直阻塞,一直不会执行,多用于权限验证。
当需要传递参数时:
package com.example.demo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* @desc:技术统计
* @author: CSH
**/
@Aspect
@Component
public class GameDataAspect {
/**
* 定义切入点,切入点为com.example.demo.aop.AopController中的所有函数
*通过@Pointcut注解声明频繁使用的切点表达式
*/
@Pointcut("execution(public * com.example.demo.aop.AopController.Durant(int)) && args(point))")
public void GameDataAspect(int point){
}
/**
* @description 使用环绕通知
*/
@Around("GameDataAspect(point)")
public void doAroundGameData(ProceedingJoinPoint pjp,int point) throws Throwable {
try{
System.out.println("球星上场前热身!");
pjp.proceed();
System.out.println("球星本场得到" + point + "分" );
}
catch(Throwable e){
System.out.println("异常通知:球迷要求退票!");
}
}
}
Spring Boot AOP的使用的更多相关文章
- Spring Boot AOP解析
Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...
- Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理
Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理 本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...
- 玩转spring boot——AOP与表单验证
AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...
- Spring Boot - AOP(面向切面)
AOP 全称 Aspect Oriented Programming(面向切面),AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分 ...
- spring boot aop打印http请求回复日志包含请求体
一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- Spring boot AOP 记录请求日志
如何将所有的通过url的请求参数以及返回结果都输出到日志中? 如果在controller的类中每个方法名都写一个log输出肯定是不明智的选择. 使用spring的AOP功能即可完成. 1. 在pom. ...
- redis分布式锁-spring boot aop+自定义注解实现分布式锁
接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
- Spring Boot AOP 扫盲,实现接口访问的统一日志记录
AOP 是 Spring 体系中非常重要的两个概念之一(另外一个是 IoC),今天这篇文章就来带大家通过实战的方式,在编程猫 SpringBoot 项目中使用 AOP 技术为 controller 层 ...
- Spring Boot AOP
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...
- Spring boot Aop 示例
需要的依赖 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -- ...
随机推荐
- Spring事务的传播级别
一.简单说明 传播属性 描述 PROPAGATION_REQUIRED 如果当前没有事务,就创建一个事务,如果当前存在事务,就加入该事务. PROPAGATION_REQUIRED_NEW 当前的方法 ...
- 执行python 爬虫脚本时提示bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?
from bs4 import BeautifulSoupfrom urllib.request import urlopenimport re html = urlopen('http://**** ...
- Appium移动端自动化测试--搭建模拟器和真机测试环境
详细介绍安装Android Studio及Android SDK.安装Appium Server. 文章目录如下 目录 文章目录如下 模拟器--安装Android Studio及Android SDK ...
- less的使用几个技巧
1.层级关系 让这个box范围内的全部包进来,这样的话就完美的进行调节,再也不用到处找第几行第几个,我刚才在哪个位置给覆盖了.一看便知! .box{ width: 100%; height: 300p ...
- 数据库基础01-SQL基础语法
数据库查询语言(Structured Query Language) 数据库查询语言: DDL(data definition language) -数据定义语言,建库建表 DML (data man ...
- OAuth 2.0 授权方式讲解,规范实践和应用
基于实践说规范 网上看了一些OAuth 2.0的授权方法,尽管讲解的没有什么逻辑性错误,但是存在一个问题,那就是单纯的讲解协议规范却脱离了实际的应用,缺少干货,所以才有了这篇文章,内容基于实际业务进行 ...
- 重学 Java 设计模式:实战模版模式「模拟爬虫各类电商商品,生成营销推广海报场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 黎明前的坚守,的住吗? 有人举过这样一个例子,先给你张北大的录 ...
- docker自动化部署前端项目实战一
docker自动化部署前端项目实战一 本文适用于个人项目,如博客.静态文档,不涉及后台数据交互,以部署文档为例. 思路 利用服务器node脚本,监听github仓库webhook push事件触发po ...
- C#字符串拼接
var name = "李哈哈"; var t = $"我是{name}";
- Python 列表生成式 生成器
[x for x in os.listdir("F:\XXX")] 生成器(x * x for x in range(10)) 如果列表元素按照某种算法推算出来,那我们就可以在循环 ...