简单来说讲,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

AOP几个术语


  1. 切面

切面是通知和切点的结合。通知和切点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能。比如事务管理是一个切面,权限管理也是一个切面。

  1. 通知

通知定义了切面是什么以及何时使用。

Spring切面中定义了5个通知类型:

* 前置通知:在目标方法调用之前执行

* 后置通知:在目标方法调用之后执行

* 返回通知:在目标方法成功执行之后执行

* 异常通知:在目标方法抛出异常之后执行

* 环绕通知:通知包裹了方法,可同时定义前置和后置通知。

  1. 切点

切点定义了在何处工作,也就是在那个方法应用通知。

  1. 连接点

连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为

  1. 引入

引入让一个切面可以声明被通知的对象实现了任何他们没有真正实现的额外接口,而且为这些对象提供接口的实现。

引入允许我们向现有的类添加新方法或属性。这个新方法和实例变量就可以被引入到现有的类中,从而可以再无需修改这些现有的类的情况下,让它们具有新的行为和状态。

  1. 织入

织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以织入。

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("异常通知:球迷要求退票!");
}
}
}

参考文章:https://www.cnblogs.com/LemonFive/p/10983875.html

Spring Boot AOP的使用的更多相关文章

  1. Spring Boot AOP解析

    Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...

  2. Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理

    Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理   本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...

  3. 玩转spring boot——AOP与表单验证

    AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...

  4. Spring Boot - AOP(面向切面)

    AOP 全称 Aspect Oriented Programming(面向切面),AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分 ...

  5. spring boot aop打印http请求回复日志包含请求体

    一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  6. Spring boot AOP 记录请求日志

    如何将所有的通过url的请求参数以及返回结果都输出到日志中? 如果在controller的类中每个方法名都写一个log输出肯定是不明智的选择. 使用spring的AOP功能即可完成. 1. 在pom. ...

  7. redis分布式锁-spring boot aop+自定义注解实现分布式锁

    接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...

  8. Spring Boot AOP 扫盲,实现接口访问的统一日志记录

    AOP 是 Spring 体系中非常重要的两个概念之一(另外一个是 IoC),今天这篇文章就来带大家通过实战的方式,在编程猫 SpringBoot 项目中使用 AOP 技术为 controller 层 ...

  9. Spring Boot AOP

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...

  10. Spring boot Aop 示例

    需要的依赖 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -- ...

随机推荐

  1. 4W字的后端面试知识点总结(持续更新)

    点赞再看,养成习惯,微信搜索[三太子敖丙]关注这个互联网苟且偷生的工具人. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的 ...

  2. GAN网络从入门教程(一)之GAN网络介绍

    GAN网络从入门教程(一)之GAN网络介绍 稍微的开一个新坑,同样也是入门教程(因此教程的内容不会是从入门到精通,而是从入门到入土).主要是为了完成数据挖掘的课程设计,然后就把挖掘榔头挖到了GAN网络 ...

  3. 【区间DP】低价回文

    [区间DP]低价回文 标签(空格分隔): 区间DP 回文词 [题目描述] 追踪每头奶牛的去向是一件棘手的任务,为此农夫约翰安装了一套自动系统.他在每头牛身上安装了一个电子身份标签,当奶牛通过扫描器的时 ...

  4. mac篇---使用iTerm2快捷连接SSH

    大家都知道使用iTerm2连接shh 使用命令 ssh -p22 root@129.10.10.1,然后输入密码即可. 但是每次都输入还是比较麻烦的.iTerm2为我们提供了快捷的方式.三步即可完成此 ...

  5. unity Prefab 序列化一个小问题。

    情景: unity之前编辑过一个字段 A, 可以再unity编辑器编辑, 之后不用了. 后来有另外的功能, 起了同样的变量名,发现有默认值. 原因: 是因为序列化的时候把A字段存储到了prefab里面 ...

  6. CentOS7下安装Docker《超详细新手教程》

    1.使用 root 权限登录 Centos.确保 yum 包更新到最新. sudo yum update 2.卸载旧版本(如果安装过旧版本的话) sudo yum remove docker dock ...

  7. 从零开始学Electron笔记(二)

    在之前的文章我们简单介绍了一下Electron可以用WEB语言开发桌面级应用,接下来我们继续说一下Electron的菜单创建和事件绑定. 我们接上一章的代码继续编写,上一章代码 https://www ...

  8. UDP/TCP 流程与总结

    1 UDP流程 前序:可以借助网络调试助手工具进行使用 1 UDP 发送方 1 创建UDP套接字 2 准备目标(发送方) IP和端口 3 需要发送的数据内容 4 关闭套接字 from socket i ...

  9. 【题解】p2388阶乘之乘

    原题传送门 题解一堆\(O(n)\)算法真给我看傻了. 考虑\(10=2*5\),因子2肯定更多,所以计算因子5的个数即可. 从5到n这\(n-5+1\)个数的阶乘里面,都各自含有一个因子\(5=1* ...

  10. Video.js随笔记

    下载与介绍 Video.js是一款web视频播放器,支持html5和flash两种播放方式.更有自定义皮肤,插件,组件,语言还有丰富的选项配置. 官网下载地址:https://videojs.com/ ...