需要的依赖

<!-- 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 示例的更多相关文章

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

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

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

  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 发送邮件示例

    最近的一个项目中用到了邮件发送,所以研究了一下.将其总结下来. 首先 登录邮箱 -->设置-->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务--> ...

随机推荐

  1. FreeRTOS任务运行时间信息统计

    相关宏的设置 configGENERATE_RUN_TIME_STATS //使能 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() //配置一个高精度定时器/计数器提 ...

  2. app后端设计(php)

    来源:http://blog.csdn.net/column/details/mobilebackend.html?page=1 做了3年app相关的系统架构,api设计,先后在3个创业公司中工作,经 ...

  3. 只要200行JavaScript代码,就能把特斯拉汽车带到您身边

    Jerry的前一篇文章 如何使用JavaScript开发AR(增强现实)移动应用 (一) 介绍了用React-Native + ViroReact开发增强现实应用的一些预备知识. 本文咱们开始进入增强 ...

  4. 关于MySql升级JDBC架包导致时区问题报错(The server time zone value '?й???????' is unrecognized or represents more than one time zone)

    报错信息: The server time zone value '?й???????' is unrecognized or represents more than one time zone. ...

  5. idea中添加多级父子模块

    在 IntelliJ IDEA 中,没有类似于 Eclipse 工作空间(Workspace)的概念,而是提出了Project和Module这两个概念. 在 IntelliJ IDEA 中Projec ...

  6. 使用Cloudera Manager搭建Impala环境

    使用Cloudera Manager搭建Impala服务 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.使用CM安装Imapala 1>.进入CM的服务安装向导 2> ...

  7. JAVA 的8种基本数据类型

    整型 int 一般的数据 long 极大的数据 short 用于特定的场合,比如底层的文件处理或者需要控制占用存储单元空间量的大数组 byte 用于特定的场合,比如底层的文件处理或者需要控制占用存储单 ...

  8. win10安装Pytorch【最新版】

    由于2019年4月16日和25日清华和中科大分别宣布停止Anaconda镜像服务,因此从2019年5月开始安装Pytorch都会出现一下错误: CondaHTTPError: HTTP 404 NOT ...

  9. java常用日期类型转换

    import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import j ...

  10. 双向认证下rpc-gateway使用(同时提供rpc和http服务)

    下载go get -v github.com/grpc-ecosystem/grpc-gateway,然后把这个包下面的third-party下面的google文件夹拷贝到Prod.proto的同级目 ...