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

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. js进度条

    第一步//====================.wrap,.circle,.percent{                  position: absolute;                ...

  2. JDK8 日期格式化

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...

  3. Python必须知道的异常处理

    异常处理 把可能会发生的错误,提前在代码里进行捕捉(监测) try : code except Exception: 出错后要执行的代码 下面是常见的异常: attributeError 试图访问一个 ...

  4. BZOJ3573 米特运输 题解

    题目 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题.D星上有N个城市,我们将其顺序编号为1到N,1号城市为首都.这N个城市由 ...

  5. mysql--数据插入覆盖和时间戳的问题

    1.数据插入问题 当我们insert数据时,插入datetime类型,此类型的字段,存储数据格式为:  YYYY-MM-DD,它支持的范围为'1000-01-01'到'9999-12-31',并且允许 ...

  6. 上海python14期第一次周考

    上海python14期第一次周考 1 介绍 满分50分 考试范围: Python语法 数据类型 流程控制 考试时间: 周五下午3.00点-晚6:00 2 基础题(38分) 什么是编程语言?什么是语言? ...

  7. include文件包含漏洞

    发现allow_url_include 是on状态 既然已经直接包含了phpinfo()是文件,首先搜索了一下allow_url_include,发现是处于打开的状态. 既然 allow_url_in ...

  8. 二、python 中五种常用的数据类型

    一.字符串 单引号定义: str1 = 'hello' 双引号定义: str1 = "hello" 三引号定义:""" 人生苦短, 我用python! ...

  9. (二)pandas处理丢失数据

    处理丢失数据 有两种丢失数据: None np.nan(NaN) import numpy as np type(None) NoneType type(np.nan) float 1. None N ...

  10. java 面向对象(一):类与对象

    1.面向对象学习的三条主线: * 1.Java类及类的成员:属性.方法.构造器:代码块.内部类 * * 2.面向对象的大特征:封装性.继承性.多态性.(抽象性) * * 3.其它关键字:this.su ...