java spring 面向切面编程_Spring Boot实战系列(3)AOP面向切面编程
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 spring 面向切面编程_Spring Boot实战系列(3)AOP面向切面编程相关推荐
- java springboot aop_Spring Boot实战系列(3)AOP面向切面编程
AOP是一种与语言无关的程序思想.编程范式.项目业务逻辑中,将通用的模块以水平切割的方式进行分离统一处理,常用于日志.权限控制.异常处理等业务中. 快速导航 编程范式主要以下几大类 AOP(Aspec ...
- Spring Boot实战系列《六》:人事管理系统的登录设计
Spring Boot实战系列<六>:人事管理系统的登录设计 Spring Boot实战系列<六>:人事管理系统的登录设计 1.前言 在上一篇中教大家在IEDA或者eclips ...
- Spring Boot 实战系列课程终于齐啦~
Spring Boot 如今已成为 Java 开发必学技术,其可以大大简化 Spring 应用的初始搭建以及开发过程. Spring Boot 不仅支持直接嵌入 Tomcat,Jetty 或 Unde ...
- springboot 后台模板_spring boot实战
亲们,我们今天来看看spring boot.如果你掌握了Servlet.JSP.Filter.Listener等web开发技术,掌握了Spring MVC.Spring.Mybatis框架的使用,掌握 ...
- springboot controller 分页查询_Spring Boot实战分页查询附近的人:Redis+GeoHash+Lua
前言 最近在做社交的业务,用户进入首页后需要查询附近的人: 项目状况:前期尝试业务阶段: 特点: 快速实现(不需要做太重,满足初期推广运营即可) 快速投入市场去运营 收集用户的经纬度: 用户在每次启动 ...
- springboot controller 分页查询_Spring Boot实战分页查询附近的人: Redis+GeoHash+Lua
您的支持是我不断创作巨大动力 CSDN博客地址(关注,点赞) 人工智能推荐 GitHub(Star,Fork,Watch) 前言 最近在做社交的业务,用户进入首页后需要查询附近的人: 项目状况:前期尝 ...
- 切面是异步还是同步操作‘_Autofac的AOP面向切面编程研究
什么是AOP: 我的理解是 把系统性的编程工作封装起来 =>我给这个取个名字叫 "Aspect",然后通过AOP技术把它切进我们的业务逻辑代码 => "业务& ...
- springboot切面返回值_SpringBoot实战15-Spring基础-AOP
上篇我们学习了<SpringBoot实战14-Spring基础-Spring EL表达式>,本篇我们学习面向切面编程AOP. 7 AOP 面向切面编程(Aspect-Oriented Pr ...
- springboot 拦截器_Spring Boot入门系列(十)如何使用拦截器,一学就会!
前面介绍了Spring Boot 如何整合定时任务已经Spring Boot 如何创建异步任务,不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhon ...
最新文章
- java中静态变量和静态方法分别有什么特点?
- MonoBehaviour生命周期
- go中的WebSocket
- 高仿国美在线底部代码实现
- where is language of sap.ui.getCore().getConfiguration set - locale
- 【吉比特】G-bits2017技术类岗位编程题
- scala学习手记28 - Execute Around模式
- 用java做一个截图工具_Java制作屏幕截图软件(还可以保存到剪切板内)
- 报错,atmSecondMenu.vue?bcc9:231 Uncaught (in promise) TypeError: Cannot read property ‘length‘ of null
- (17)System Verilog枚举类型enum详解
- 深度解读SSH免密登录
- NM3200多用表校验仪
- html 让360浏览器兼容模式,360浏览器兼容模式怎么设置?360浏览器兼容模式设置方法介绍...
- 【短道速滑四】Halcon的texture_laws算子自我研究
- git push报错 rejected
- python 穷举密码
- Android studio通过科大讯飞的SDK实现文字转语音功能
- Fine BI、Smart BI、永洪BI、瓴羊Quick BI这些国产BI工具,都擅长哪些功能?
- 简单演示程序序列号的破解
- Python安装Selenium