Spring boot Aop 示例
需要的依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
ASPECT
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.org.apache.xpath.internal.operations.String;
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; @Aspect
@Component
public class LogAspect { private final static Logger logger = LoggerFactory.getLogger(LogAspect.class); // * 表示所有返回类型 ..表示包及子包 * 表示所有类 .* 指类所有方法 (..) 代表所有参数
@Pointcut("execution(public * com.gailguo.demo.controller..*.*(..))")
public void controllerMethod() {
} @Before("controllerMethod()")
public void LogRequestInfo(JoinPoint joinPoint) throws Exception { logger.info("请求结果: Before " ); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest(); StringBuffer requestLog = new StringBuffer();
requestLog.append("请求信息:")
.append("URL = {" + request.getRequestURI() + "},\t")
.append("HTTP_METHOD = {" + request.getMethod() + "},\t")
.append("IP = {" + request.getRemoteAddr() + "},\t")
.append("CLASS_METHOD = {" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + "},\t"); if(joinPoint.getArgs().length == 0) {
requestLog.append("ARGS = {} ");
} else {
requestLog.append("ARGS = " + new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL)
.writeValueAsString(joinPoint.getArgs()[0]) + "");
} logger.info(requestLog.toString());
} @AfterReturning( pointcut = "controllerMethod()")
public void logResultVOInfo() throws Exception {
logger.info("请求结果: after return " );
} @After("controllerMethod()")
public void logAfter(JoinPoint joinPoint){
logger.info("请求结果: after " );
} @AfterThrowing("controllerMethod()")
public void logException(JoinPoint joinPoint){
logger.info("请求结果: after AfterThrowing " );
} @Around("controllerMethod()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable{ Object s=null;
if(joinPoint.getArgs().length>0){
s=joinPoint.getArgs()[0];
logger.info("Around: 打印传参 "+s.toString() );
}
logger.info("Around 1");
Object obj=joinPoint.proceed(new Object[]{"sss+"+s.toString()});
logger.info("Around 2");
return obj; } }
一个简单的controller
@RestController
@RequestMapping(path = "/aop")
public class MyController { @RequestMapping(path ="/test")
public String getTest(@RequestParam("id")String id){
return "111"+id;
}
}
Pointcut 执行表达式的格式
参考
https://elim.iteye.com/blog/2395255
1: execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
除了返回类型模式(上面代码片断中的ret-type-pattern),
名字模式和参数模式以外,所有的部分都是可选的。
返回类型模式决定了方法的返回类型必须依次匹配一个连接点。
你会使用的最频繁的返回类型模式是 * ,它代表了匹配任意的返回类型。
一个全称限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。
你可以使用 * 通配符作为所有或者部分命名模式。
参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方法, 而 (..) 匹配了一个接受任意数量参数的方法(零或者更多)。
模式 (*) 匹配了一个接受一个任何类型的参数的方法。
模式 (*,String) 匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型。
一些常见切入点表达式的例子
execution(public * *(..)) 任意公共方法的执行;
execution(* set*(..)) 任何一个以“set”开始的方法的执行;
execution(* com.xyz.service.AccountService.*(..)) AccountService接口的任意方法的执行;
execution(* com.xyz.service.*.*(..)) 定义在service包里的任意方法的执行;
execution(* com.xyz.service..*.*(..)) 定义在service包或者子包里的任意方法的执行;
2. within 是用来指定类型的,指定类型中的所有方法将被拦截
3. bean
bean用于匹配当调用的是指定的Spring的某个bean的方法时。
“bean(abc)”匹配Spring Bean容器中id或name为abc的bean的方法调用。
“bean(user*)”匹配所有id或name为以user开头的bean的方法调用。
@Component
public class TestInfo { Logger logger= LoggerFactory.getLogger(TestInfo.class); public void testInfo(){
logger.info("这里是testInfo 方法");
}
}
@Pointcut("bean(testInfo)")
public void controllerMethod2(){ }
@Around("controllerMethod2()")
public Object logAround2(ProceedingJoinPoint joinPoint) throws Throwable{ logger.info("Around testInfo 1");
Object obj=joinPoint.proceed();
logger.info("Around testInfo 2");
return obj; }
@Autowired
TestInfo info; @RequestMapping(path ="/test")
public String getTest(@RequestParam("id")String id){
info.testInfo();
return "111"+id;
}
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 全称 Aspect Oriented Programming(面向切面),AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分 ...
- 玩转spring boot——AOP与表单验证
AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...
- 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 发送邮件示例
最近的一个项目中用到了邮件发送,所以研究了一下.将其总结下来. 首先 登录邮箱 -->设置-->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务--> ...
随机推荐
- c# zip写comment注释
//生成的压缩文件为test.zip using (FileStream fsOut = File.Create("test.zip")) { //ZipOutputStream类 ...
- python3实现unix域协议(tcp、udp)通讯
socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIXDomain Socket.虽然网络socket也可用于同一台主机的进程间通讯(通过loopb ...
- Android笔记(四十六) Android中的数据存储——XML(二)PULL解析
PULL 的工作原理: XML pull提供了开始元素和结束元素.当某个元素开始时,可以调用parser.nextText()从XML文档中提取所有字符数据.当解析到一个文档结束时,自动生成EndDo ...
- [ike][ipsec] child sa rekey机制的细节分析
子标题:ipsec rekey是否会导致丢包 author: classic_tong 前言 什么叫rekey. rekey是指ipsec的通信两端定期更换加密信道秘钥的机制. 为了安全性考虑,随着秘 ...
- 【转】TCP之深入浅出send和recv
本篇我们用一个测试机上的阻塞socket实例来说明主题.文章中所有图都是在测试系统上现截取的. 需要理解的3个概念 1. TCP socket的buffer 每个TCP socket在内核中都有一个发 ...
- STM32+IAR 解决Error[Pe147]: declaration is incompatible with "__nounwind __interwork __softfp unsigned
在IAR中编译STM32工程,遇到 Error[Pe147]: declaration is incompatible with "__nounwind __interwork __soft ...
- C++(三十六) — 等号操作符重载、&&,||不可重载
1.等号操作符重载,实现深拷贝 //等号运算符重载 // obj3=obj1;//原始的是浅拷贝,现在要重载为深拷贝 Name& operator=(Name &obj1) { //1 ...
- 学习markdown(一)
转:https://www.jianshu.com/p/81e1608ea2d8 ----------------------------------------------------------- ...
- 倍增法求lca:暗的连锁
https://loj.ac/problem/10131 #include<bits/stdc++.h> using namespace std; struct node{ int to, ...
- 1210 BBS admin后台管理及侧边栏筛选个人站点
目录 昨日内容 django admin后台管理 使用 建表 用户图片的显示 MEDIA用户配置 查找照片 搭建个人站点 防盗链 新建css文件 侧边栏展示标签 定义分类栏与标签栏 定义时间栏 侧边栏 ...