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服务--> ...
随机推荐
- svg实现圆环进度条
开源实现:https://github.com/lugolabs/circles 自行实现:圆环与svg画布间剩的空间太多. <!DOCTYPE html> <html> &l ...
- Hadoop常用命令及范例
hadoop中的zookeeper,hdfs,以及hive,hbase都是hadoop的组件,要学会熟练掌握相关的命令及其使用规则,下面就是一些常用命令及对hbase和hive的操作语句,同时也列出了 ...
- oracle批量操作
https://stackoverflow.com/questions/39576/best-way-to-do-multi-row-insert-in-oracle 1 批量insert 方式一: ...
- spark 机器学习 决策树 原理(一)
1.什么是决策树 决策树(decision tree)是一个树结构(可以是二叉树或者非二叉树).决策树分为分类树和回归树两种,分类树对离散变量做决策树,回归树对连续变量做决策树. 其中每个非叶节点表示 ...
- Android笔记(五十五) Android四大组件之一——ContentProvider,使用系统提供的ContentProvider
因为在Android中,存储系统联系人姓名和电话是存在与不同的ContentProvider中的,具体如何查找,可以从Android的源代码中查看,在android.providers包中列出了所有系 ...
- Android笔记(五十四) Android四大组件之一——ContentProvider(一)
ContentProvider提供数据 在Android中,他的每个应用都是相互独立的,各自运行在自己的Dalvik虚拟机中,但现实使用中常常需要在多个应用之间进行数据交换,例如发短信需要获取联系人中 ...
- Please provide compiled classes of your project with sonar.java.binaries property
是因为一个jar包版本的原因,sonar-java-plugin-5.1.0.13090.jar 需要降级 https://repo.maven.apache.org/maven2/org/sonar ...
- 分布式调度平台XXL-JOB源码分析-调度中心
架构图 上图是我们要进行源码分析的2.1版本的整体架构图.其分为两大块,调度中心和执行器,本文先分析调度中心,也就是xxl-job-admin这个包的代码. 关键bean 在application.p ...
- JAVA BIO至NIO演进
主要阐述点: 1.同步/异步 or 阻塞/非阻塞 2.网络模型演进 3.NIO代码示例 一.同步/异步 or 阻塞/非阻塞 同步/异步:核心点在于是否等待结果返回.同步即调用者必须等到结果才返回, ...
- linux 导出mysql数据库表及数据
导出表及结构 mysqldump -h地址ip -u用户名 -p密码 数据库名 > 数据库名.sql --连接数据库 mysql -h地址ip -u用户名 -p密码 --使用数据库 user ...