AOP是一种与语言无关的程序思想、编程范式。项目业务逻辑中,将通用的模块以水平切割的方式进行分离统一处理,常用于日志、权限控制、异常处理等业务中。

快速导航

编程范式主要以下几大类

AOP(Aspect Oriented Programming)面向切面编程

OOP(Object Oriented Programming)面向对象编程

POP(procedure oriented programming)面向过程编程

FP(Functional Programming)面向函数编程

引入aop依赖

项目根目录 pom.xml 添加依赖 spring-boot-starter-aop

org.springframework.boot

spring-boot-starter-aop

aop注解

@Aspect: 切面,由通知和切入点共同组成,这个注解标注在类上表示为一个切面。

@Joinpoint: 连接点,被AOP拦截的类或者方法,在前置通知中有介绍使用@Joinpoint获取类名、方法、请求参数。

Advice: 通知的几种类型

@Before: 前置通知,在某切入点@Pointcut之前的通知

@After: 后置通知,在某切入点@Pointcut之后的通知无论成功或者异常。

@AfterReturning: 返回后通知,方法执行return之后,可以对返回的数据做加工处理。

@Around: 环绕通知,在方法的调用前、后执行。

@AfterThrowing: 抛出异常通知,程序出错跑出异常会执行该通知方法。

@Pointcut: 切入点,从哪里开始。例如从某个包开始或者某个包下的某个类等。

实现日志分割功能

目录 aspect下 新建 httpAspect.java类,在收到请求之后先记录请求的相关参数日志信息,请求成功完成之后打印响应信息,请求处理报错打印报错日志信息。

httpAspect.java

package com.angelo.aspect;

import com.google.gson.Gson;

import com.google.gson.GsonBuilder;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.*;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import org.springframework.web.context.request.RequestContextHolder;

import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import java.util.HashMap;

import java.util.Map;

@Aspect

@Component

public class HttpAspect {

// 打印日志模块

private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);

// 下面会一一介绍...

添加切入点

定义切入的入口在哪里,封装一个公共的方法实现复用

httpAspect.java

/**

* 定义一个公共的方法,实现服用

* 拦截UserController下面的所有方法

* 拦截UserController下面的userList方法里的任何参数(..表示拦截任何参数)写法:@Before("execution(public * com.angelo.controller.UserController.userList(..))")

*/

@Pointcut("execution(public * com.angelo.controller.UserController.*(..))")

public void log() {

}

前置通知

拦截方法之前的一段业务逻辑,获取请求的一些信息,其中用到了Gson处理对象转json输出

httpAspect.java

@Before("log()")

public void doBefore(JoinPoint joinPoint) {

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

HttpServletRequest request = attributes.getRequest();

Map params = new HashMap();

params.put("url", request.getRequestURL()); // 获取请求的url

params.put("method", request.getMethod()); // 获取请求的方式

params.put("ip", request.getRemoteAddr()); // 获取请求的ip地址

params.put("className", joinPoint.getSignature().getDeclaringTypeName()); // 获取类名

params.put("classMethod", joinPoint.getSignature().getName()); // 获取类方法

params.put("args", joinPoint.getArgs()); // 请求参数

// 输出格式化后的json字符串

Gson gson = new GsonBuilder().setPrettyPrinting().create();

logger.info("REQUEST: {}", gson.toJson(params));

}

后置通知

拦截方法之后的一段业务逻辑

httpAspect.java

@After("log()")

public void doAfter() {

logger.info("doAfter");

}

环绕通知

环绕通知是在方法的前后的一段逻辑操作,可以修改目标方法的返回值,第一个参数是org.aspectj.lang.ProceedingJoinPoint类型,注意这里要调用执行目标方法proceed()获取值返回,不然会造成空指针异常。在环绕通知里面也可以捕获错误返回。

httpAspect.java

@Around("log()")

public Object doAround(ProceedingJoinPoint point) {

try {

Object o = point.proceed();

System.out.println("方法环绕proceed,结果是 :" + o);

logger.info("doAround1");

return o;

} catch (Throwable e) {

// e.printStackTrace();

logger.info("doAround2");

return null;

}

}

返回后通知

在切入点完成之后的返回通知,此时就不会抛出异常通知,除非返回后通知的业务逻辑报错。

httpAspect.java

/**

* 获取响应返回值

* @param object

*/

@AfterReturning(returning = "object", pointcut = "log()")

public void doAfterReturning(Object object) {

// logger.info("RESPONSE: {}", object); 会打印出一个对象,想打印出具体内容需要在定义模型处加上toString()

logger.info("RESPONSE: {}", object.toString());

}

异常通知

抛出异常后的通知,此时返回后通知@AfterReturning就不会执行。

httpAspect.java

@AfterThrowing(pointcut = "log()")

public void doAfterThrowing() {

logger.error("doAfterThrowing: {}", " 异常情况!");

}

一段段伪代码读懂执行顺序

try {

// @Before 执行前通知

// 执行目标方法

// @Around 执行环绕通知 成功走finall,失败走catch

} finally {

// @After 执行后置通知

// @AfterReturning 执行返回后通知

} catch(e) {

// @AfterThrowing 抛出异常通知

}

测试正常异常两种情况

测试之前先对controller/UserController.java文件的userList方法增加了exception参数

/**

* 查询用户列表

* @return

*/

@RequestMapping(value = "/user/list/{exception}")

public List userList(@PathVariable("exception") Boolean exception) {

if (exception) {

throw new Error("测试抛出异常!");

}

return userRepository.findAll();

}

测试正常情况

curl 127.0.0.1:8080/user/list/false

正常情况返回值如下所示:

测试异常情况

curl 127.0.0.1:8080/user/list/true

异常情况返回值如下所示:

通过以上两种情况测试可以看到环绕通知在正常、异常两种情况都可以执行到。

java springboot aop_Spring Boot实战系列(3)AOP面向切面编程相关推荐

  1. java spring 面向切面编程_Spring Boot实战系列(3)AOP面向切面编程

    AOP是一种与语言无关的程序思想.编程范式.项目业务逻辑中,将通用的模块以水平切割的方式进行分离统一处理,常用于日志.权限控制.异常处理等业务中. 快速导航 编程范式主要以下几大类 AOP(Aspec ...

  2. SpringBoot之AOP面向切面编程实例

    目录 1.引入pom依赖 2.切入点表达式 --组成 --逻辑运算符 --通配符 --范例 3. 启动类配置 4.通知类型 4.1 @Before : 标注当前方法作为前置通知 4.1.1 创建自定义 ...

  3. java aop面向切面编程

    最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblog ...

  4. Springboot 一文搞懂AOP面向切面编程

    Springboot AOP面向切面编程 AOP简介 AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构. 作用:在不惊动原始设计的 ...

  5. 【SSM】Spring系列——AOP面向切面编程

    文章目录 03 AOP面向切面编程 3.1 AOP概述 3.2 面向切面编程对有什么好处 3.3 模拟AOP框架实现 3.3.1 代码实现版本一 3.3.2 代码实现版本二 3.3.3 代码实现版本三 ...

  6. Java绝地求生—Spring AOP面向切面编程

    Java绝地求生-Spring AOP面向切面编程 背景 动态代理 构建被代理对象 自动生成代理 调用动态代理 Spring方法 方式一:使用Spring的API接口 方式二:使用自定义类 方式三:使 ...

  7. python aop编程_学习笔记: AOP面向切面编程和C#多种实现

    AOP:面向切面编程   编程思想 OOP:一切皆对象,对象交互组成功能,功能叠加组成模块,模块叠加组成系统 类--砖头     系统--房子 类--细胞     系统--人 面向对象是非常适合做大型 ...

  8. spring中AOP(面向切面编程)

    spring中AOP(面向切面编程) 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是spring框架中的一个重要内容 ...

  9. AOP面向切面编程之全局日志打印/统计接口耗时

    目录 一.什么是AOP 二.AOP使用场景 三.使用AOP的好处 四.先举个例子理解AOP面向切面编程 五.Spring5.X的AOP切入点表达式有这些种写法 六.实战基于Spring的AOP快速实现 ...

最新文章

  1. PyQt5 Introduction and components
  2. python list转矩阵
  3. 程序员法律考试(5)-民法(2)
  4. Java基础篇:四种代码块详解
  5. im2col原理小结
  6. Merge Into 语句代替Insert/Update在Oracle中的应用实战
  7. docker 中文文档_Kubernetes将弃用Docker,不必恐慌
  8. 蓝牙uuid是什么意思_小公主的吐槽非常好|米家蓝牙温湿度计2
  9. 数据库、SQL脚本、存储过程执行准则(*****)
  10. 计分及竞赛软件启动时的错误现象及解决方法
  11. 三年级下册我想发明的机器人_我想发明的机器人作文300字
  12. unix编程实训教程之 more(觉醒篇一 Begin)
  13. 免杀Payload生成工具Veil的下载与使用
  14. 在IEEE会议论文LaTeX模板中添加页码
  15. PHP工具箱无法启动Mysql问题
  16. win10锁屏壁纸文件夹位置
  17. 永磁同步电机的矢量控制策略(八)一一一仿真模型搭建与源代码
  18. C语言程序设计入门——平均值
  19. 【资讯分享】云帆加速将P2P技术免费,该服务量级已突破1.5T
  20. Linux之find 命令

热门文章

  1. linux 时间戳计数器,使用TSC(时间戳计数器)计算时间
  2. 证书服务器web注册,无法通过 Web 注册请求证书 - Windows Server | Microsoft Docs
  3. java camel swagger,Swagger将下划线转换为camelcase
  4. java 动软_动软代码生成器下载_2017动软代码生成器下载及相关推荐 - noYes软件大全...
  5. java与模式孙悟空_悟空模式-java-工厂方法模式
  6. python telnet server_python工具库介绍-dubbo:通过telnet接口访问dubbo服务
  7. python必须连网开发吗_Python以太坊开发节点和网络选择
  8. mysql修改字段结构_MySQL修改表结构及其添加删除修改字段功能
  9. Linux Polkit 中的pkexec 组件存在的本地权限提升漏洞(CVE-2021-4034)修复方法及centos6和centos7的安装包
  10. Apache POI学习笔记