目录

1.什么是AOP切面

2.理解AOP

3.AOP实例

1.自定义注解

2.创建一个切面类

3.将自定义注解标注在测试接口上


1.什么是AOP切面

AOP(Aspect Oriented Programming),面向切面思想,是Spring的三大核心思想之一。

在项目中经常会有些系统性的需求,例如权限校验,日志记录,统计等,这时我们就可以通过AOP切面去实现。

有多少业务代码就需要写多少重复校验和日志记录,这显然是不合理的,我们可以把这些重复操作抽离出来,写成公共的方法。

这样,代码冗余解决了,但是每个地方都要手动去调用还是很麻烦,有没有更好的方式呢?这就要用到我们的AOP(面向切面编程),AOP将权限校验,日志记录等非业务代码提取出来,和业务代码完全分离,并寻找节点切入业务代码中

2.理解AOP

简单理解AOP,AOP主要做三件事

  1. 在哪里切入,也就是日志记录等非业务代码在哪些业务代码中执行。
  2. 在什么时候切入,是在业务代码执行前还是后。
  3. 切入后做什么事情,比如权限校验,日志记录等

理解如下图

一些概念理解:

Pointcut:切点,决定处理如权限校验、日志记录等在何处切入业务代码中(即织入切面)。切点分为execution方式和annotation方式。前者可以用路径表达式指定哪些类织入切面,后者可以指定被哪些注解修饰的代码织入切面。
Advice:处理,包括处理时机和处理内容。处理内容就是要做什么事,比如校验权限和记录日志。处理时机就是在什么时机执行处理内容,分为前置处理(即业务代码执行前)、后置处理(业务代码执行后)等。
Aspect:切面,即Pointcut和Advice。
Joint point:连接点,是程序执行的一个点。例如,一个方法的执行或者一个异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。
Weaving:织入,就是通过动态代理,在目标对象方法中执行处理内容的过程。

3.AOP实例

  1. 自定义一个注解OperationLogAnnotation
  2. 创建一个切面类,切点设置为拦截标注OperationLogAnnotation的方法,截取传参,进行日志记录
  3. 将OperationLogAnnotation标注在测试接口上

具体的实现步骤如下:

1.自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLogAnnotion {//操作类型@NonNullOperationType type();//操作对象@NonNullOperationObjectType objType();}
public enum OperationType {CREATE("create"),UPDATE("update"),DELETE("delete"),ADD("add");private String type;OperationType(String type){this.type=type;}public String getType() {return type;}public void setType(String type) {this.type = type;}
}
public enum OperationObjectType {USER("user"),//项目PROJECT("project"),//页面管理PROJECT_PAGE("project page"),//人员管理ROLE_USER("role user"),//角色页面管理ROLE_PAGE("role page");private String objType;OperationObjectType(String objType){this.objType=objType;}public String getObjType() {return objType;}public void setObjType(String objType) {this.objType = objType;}
}

2.创建一个切面类

@Aspect
@Component
public class LogAdvice implements ApplicationListener<ContextRefreshedEvent> {private BlockingQueue<OperationLog> operationLogQ = new LinkedBlockingDeque<>();@Autowiredprivate IOperationLogService operationLogService;private static final Logger LOGGER = LogManager.getLogger();@Pointcut("@annotation(com.pwd.springdemo.aop.annotation.OperationLogAnnotion)")public void logAdvicePointcut(){}@AfterReturning(pointcut = "logAdvicePointcut()  && @annotation(operationLogAnnotion)", returning = "returnResult")public void logAdvice(JoinPoint joinPoint, com.pwd.springdemo.aop.annotation.OperationLogAnnotion operationLogAnnotion, Object returnResult){try {if (!(returnResult instanceof ResultInfo)) {return;}//filter failed requestResultInfo result = (ResultInfo) returnResult;if (result.getCode() != ResultCode.SUCCESS.getCode()) {return;}HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();Object[] args = joinPoint.getArgs();String requestParams = JSONObject.toJSONString(args);String userIp = request.getHeader("UserIp");User user = (User) request.getSession().getAttribute("user");String userId = null;if (user != null) {userId = user.getUserId();}String type = operationLogAnnotion.type().getType();String objType = operationLogAnnotion.objType().getObjType();Signature signature = joinPoint.getSignature();String functionName=signature.getName();OperationLog log = new OperationLog(userId, userIp, functionName,type + " " + objType, requestParams);operationLogQ.add(log);} catch (Exception e) {LOGGER.error("operation log aspect error", e);}}/*** consume queue 2 save db*/private void saveLogs() {while (true) {try {OperationLog log = operationLogQ.poll(5, TimeUnit.MILLISECONDS);if (log != null) {operationLogService.addLog(log);}} catch (Exception e) {LOGGER.error("insert operation log to db error", e);}}}@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {ExecutorService pool = new ThreadPoolExecutor(1, 1,0L, TimeUnit.SECONDS,new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setNameFormat("Save-Logs-%d").setDaemon(true).build());pool.submit(new Runnable() {@Overridepublic void run() {saveLogs();}});}
}

3.将自定义注解标注在测试接口上

    @ResponseBody@OperationLogAnnotion(type = OperationType.DELETE,objType = OperationObjectType.USER)@RequestMapping(value = "deleteUserInfoById", method = RequestMethod.POST)public ResultInfo deleteUserInfoById(@RequestBody JSONObject jsonObject) {Integer id = jsonObject.getInteger("id");LOGGER.info("id:" + id);userService.deleteUserInfoById(id);return ResultInfo.success(null);}

spring AOP切面及日志记录实现相关推荐

  1. spring aop 切面添加日志

    这是一个非常简单的spring aop切面添加日志的程序,下面来看一下这个程序 1.程序使用jar包 2.切面类LoggingAspect.java package com.cailei.aop.as ...

  2. 【经典】Spring aop切面实现异步添加日志—完整版

    系统开发中我们常遇到要处理系统日志等信息的,在此我分享一篇 利用spring aop切面来异步添加日志的操作,其中用到了 队列和多线程,前面的博客有写. 第一步:创建log实体,根据自己业务而定, p ...

  3. spring AOP切面日志

    spring AOP切面日志 导入依赖 <properties><fastjson.version>1.2.49</fastjson.version> </p ...

  4. Spring AOP 切面@Around注解的具体使用

    @Around注解可以用来在调用一个具体方法前和调用后来完成一些具体的任务. 比如我们想在执行controller中方法前打印出请求参数,并在方法执行结束后来打印出响应值,这个时候,我们就可以借助于@ ...

  5. Spring AOP切面的时候参数的传递

    Spring AOP切面的时候参数的传递 Xml: <?xml version="1.0" encoding="UTF-8"?> <beans ...

  6. Spring AOP实例——异常处理和记录程序执行时间

    Spring AOP实例--异常处理和记录程序执行时间 参考文章: (1)Spring AOP实例--异常处理和记录程序执行时间 (2)https://www.cnblogs.com/victoria ...

  7. java aop注解日志记录_springMVC自定义注解,用AOP来实现日志记录的方法

    需求背景 最近的一个项目,在项目基本完工的阶段,客户提出要将所有业务操作的日志记录到数据库中,并且要提取一些业务的关键信息(比如交易单号)体现在日志中. 为了保证工期,在查阅了资料以后,决定用AOP+ ...

  8. Spring AOP 切面记录操作日志

    前言 实际业务,有时候需要记录服务的操作日志,我们可以利用SpringAOP 切面来拦截记录用户操作:用户使用session或者前端传值都可以. 1.创建日志记录接口 首先我们得有一个接口,这个接口可 ...

  9. 日志管理(spring AOP切面拦截)

    **最近,在写日志管理的东西呢,用了几种方法试,还是拦截比较好用,直接截下来传入到数据库中存储. 写的时候,真是头疼啊. 哦~对了,忘了说了,不需要用到Dao层哦. 首先,来一个POJO实体类吧,我看 ...

  10. spring - AOP(6)- 记录后台管理员操作日志

    一.需求 1.1 问题 后台一些涉及到新增.编辑.删除等敏感操作的需要记录下操作日志,包含操作人.操作内容.请求参数等等信息. 1.2 思路 统一对Controller层的方法进行拦截,记录下请求信息 ...

最新文章

  1. 使用余弦相似度算法计算文本相似度-数学
  2. matlab找出二维矩阵中最大值的位置或者最小值的位置
  3. 【svn】svn的使用
  4. shell文件管理jenkins构建过程---window环境下报错:找不到shell文件
  5. vxWorks下常用的几种延时方法
  6. mysql常用快速查询修改操作
  7. 解决 : Could not commit JPA transaction RollbackException: Transaction marked as rollbackOnly
  8. 【Java】国外大神总结的 10 个 Java 编程技巧!
  9. 空间变量php,PHP名称空间可以包含变量吗?
  10. jemalloc优化MySQL、Nginx内存管理
  11. 【docker系列】docker深入浅出之安装Nginx+PHP+MySQL
  12. python程序员自我评价_程序员节,用一句话证明你是一个程序员
  13. 【LaTeX】对表格中的内容添加脚注不显示
  14. matlab 保存成csv,怎么将matlab中数据保存为csv或xls格式
  15. SQL查询语句教程(浅显易懂)
  16. 3D打印服务器Octoprint配置步骤
  17. LeetCode 286 Walls and Gates
  18. Data Oriented Analysis Design
  19. 物联网——Al二哈人脸识别
  20. IIS中,文件打开报错404的解决办法

热门文章

  1. 普通二重积分计算的难点、易错点
  2. 系列课程 ElasticSearch 之第 9 篇 —— ELK (ElasticSearch、Logstash、Kibana)分布式日志收集和查看(完结)
  3. matlab中的对数log()使用
  4. 测度论与概率论基础学习笔记1——1.1 集合及其运算
  5. 程序员做自媒体变现,可以选择的平台有哪些?各自的特点是什么?
  6. 最全的国内外电子书籍网站合集
  7. 谷歌google chrome浏览器Chrome版本太旧无法更新chrome无法更新至最新版本怎么办
  8. linux同花顺乱码,打开同花顺软件全是问号
  9. OSI七层网络协议(应用层:http协议、传输层:TCP协议、网络层:IP协议,数据链路层:ARP协议、网络下一跳,物理层:比特流)
  10. VS软件版本号定义、规则和相关的Visual Studio插件