使用aop去自定义注解,实现用户在请求的时候记录下来,如日志功能等
首先搞清楚aop的几个概念:
AOP即是面向切面,是Spring的核心功能之一,主要的目的即是针对业务处理过程中的横向拓展,以达到低耦合的效果。
「切面(Aspect)」:一个关注点的模块化。以注解@Aspect的形式放在类上方,声明一个切面。
「连接点(Joinpoint)」:在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候都可以是连接点。
「通知(Advice)」:通知增强,需要完成的工作叫做通知,就是你写的业务逻辑中需要比如事务、日志等先定义好,然后需要的地方再去用。增强包括如下五个方面:
@Before:在切点之前执行@After:在切点方法之后执行@AfterReturning:切点方法返回后执行@AfterThrowing:切点方法抛异常执行@Around:属于环绕增强,能控制切点执行前,执行后,用这个注解后,程序抛异常,会影响@AfterThrowing这个注解。
「切点(Pointcut)」:其实就是筛选出的连接点,匹配连接点的断言,一个类中的所有方法都是连接点,但又不全需要,会筛选出某些作为连接点做为切点。
「引入(Introduction)」:在不改变一个现有类代码的情况下,为该类添加属性和方法,可以在无需修改现有类的前提下,让它们具有新的行为和状态。其实就是把切面(也就是新方法属性:通知定义的)用到目标类中去。
「目标对象(Target Object)」:被一个或者多个切面所通知的对象。也被称做被通知(adviced)对象。既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。
「AOP代理(AOP Proxy)」:AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
「织入(Weaving)」:把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
Spring Boot 如何整合AOP自定义一个注解?
在实际开发中对于横向公共的逻辑需要抽取出来,这时候就需要使用AOP,比如日志的记录、权限的验证等等,这些功能都可以用注解轻松的完成。
添加依赖starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
自定义一个注解:
package com.example.demo.config; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog { OperationType operationType() default OperationType.SELECT; String value() default "";
}
package com.example.demo.config; /**
* @author Albert.Yang
*/ public enum OperationType {
SELECT,SAVE,UPDATE,DELETE
}
定义一个切面:
package com.example.demo.config; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; @Component
@Aspect
@Configuration
public class SysLogAspect { @Pointcut("@annotation(com.example.demo.config.SysLog)")
public void pointCut() {} @Around("pointCut()")
//@Around("@annotation(sysLog)") //2种写法,一种可以不单独写@Pointcut,而以SysLog sysLog作为入参。
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis(); //逻辑开始时间
System.out.println("@Around:执行目标方法之前...");
Object result = point.proceed(); //执行方法
System.out.println("@Around:执行目标方法之后...");
saveLog(point,beginTime);//todo,保存日志,自己完善
return result;
} private void saveLog(ProceedingJoinPoint point, long beginTime) {
System.out.println("Around-----" + beginTime + point.getSignature());
} @Before("@annotation(sysLog)")
public void doBefore(JoinPoint joinPoint, SysLog sysLog) {
System.out.println("doBefore-----" +joinPoint.getSignature() + sysLog.value());
} @AfterReturning(pointcut = "@annotation(sysLog)", returning = "returnValue")
public void releaseResource(JoinPoint joinPoint, SysLog sysLog, Object returnValue) {
System.out.println("AfterReturning-----" +joinPoint.getSignature() + sysLog.operationType().toString());
} }
测试:
以上配置完成后即可使用,只需要在需要的方法上标注@SysLog注解即可,如下:
package com.example.demo.controller; import com.example.demo.config.SysLog;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @Author Tim
* @Date 2020/11/20 11:40
*/
@RestController
public class Controller1 { @SysLog
@GetMapping("/add")
public String add(){
System.out.println("请求成功");
return "请求成功";
} }
package com.example.demo.controller; import com.example.demo.config.OperationType;
import com.example.demo.config.SysLog;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @Author Tim
* @Date 2020/11/20 11:40
*/
@RestController
public class ControlleDemo { @SysLog(operationType = OperationType.UPDATE, value = "請求2")
@GetMapping("/add2")
public String add(){
System.out.println("请求2");
return "请求2";
} }
注意有个执行顺序问题:
@Around是可以同时在所拦截方法的前后执行一段逻辑。
@Before是在所拦截方法执行之前执行一段逻辑。
@After 是在所拦截方法执行之后执行一段逻辑。

使用aop去自定义注解,实现用户在请求的时候记录下来,如日志功能等的更多相关文章
- spring AOP 和自定义注解进行身份验证
一个SSH的项目(springmvc+hibernate),需要提供接口给app使用.首先考虑的就是权限问题,app要遵循极简模式,部分内容无需验证,用过滤器不能解决某些无需验证的方法 所以最终选择用 ...
- AOP 实现自定义注解
1.自定义注解2.编写 AOP3.测试 1.自定义注解 package com.base.yun.spring.aop; import java.lang.annotation.Documented; ...
- 用AOP拦截自定义注解并获取注解属性与上下文参数(基于Springboot框架)
目录 自定义注解 定义切面 获取上下文信息JoinPoint ProceedingJoinPoint 定义测试方法 测试结果 小结 AOP可以用于日志的设计,这样话就少不了要获取上下文的信息,博主在设 ...
- 【spring boot】SpringBoot初学(6)– aop与自定义注解
前言 github: https://github.com/vergilyn/SpringBootDemo 一.AOP 官方demo:https://github.com/spring-project ...
- springboot通过AOP和自定义注解实现权限校验
自定义注解 PermissionCheck: package com.mgdd.sys.annotation; import java.lang.annotation.*; /** * @author ...
- SpringBoot中搭配AOP实现自定义注解
1 springBoot的依赖 确定项目中包含可以注解的依赖 <dependency> <groupId>org.springframework.boot</groupI ...
- Spring Boot系列——AOP配自定义注解的最佳实践
AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...
- 使用AOP获取自定义注解的内容
目录结构: 一:自定义注解 package org.example.annotation; import java.lang.annotation.ElementType; import java.l ...
- SpringBoot框架:通过AOP和自定义注解完成druid连接池的动态数据源切换(三)
一.引入依赖 引入数据库连接池的依赖--druid和面向切面编程的依赖--aop,如下所示: <!-- druid --> <dependency> <groupId&g ...
- 基于SpringBoot 、AOP与自定义注解转义字典值
一直以来,前端展示字典一般以中文展示为主,若在表中存字典值中文,当字典表更改字典值对应的中文,会造成数据不一致,为此设置冗余字段并非最优方案,若由前端自己写死转义,不够灵活,若在业务代码转义,臃肿也不 ...
随机推荐
- 数据库系列:MySQL InnoDB锁机制介绍
数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩容 数据库 ...
- 小程序的登录授权与退出功能(wx.getUserProfile)
一.授权登录:wx.getUserProfile 1.使用wx.getUserProfile实现登录 1.javascript: login(){ wx.getUserProfile({ desc: ...
- 最新版本——Hadoop3.3.6单机版完全部署指南
大家好,我是独孤风,大数据流动的作者. 本文基于最新的 Hadoop 3.3.6 的版本编写,带大家通过单机版充分了解 Apache Hadoop 的使用.本文更强调实践,实践是大数据学习的重要环节, ...
- Android Studio 学习-第三章 Activity 第一组
事先申明:所有android 类型的学习记录全部基于<第一行代码 Android>第三版,在此感谢郭霖老师的书籍帮助. 1.手动创建Activity 在Project类型目录中寻找到 项目 ...
- GSM/WCDMA/LTE/NR网元架构
1.GSM系统网元架构: 一套完整的蜂窝移动通信系统主要是由交换网络子系统(NSS).无线基站子系统(BSS).移动台(MS)及操作维护子系统(OMS)四大子系统设备组成. NSS 包括: MSC: ...
- Java8新特性之FlatMap&Reduce
1.FlagMap // flatMap:接收一个T返回一个R,将一个元素转为一个新的流 ;R apply(T t); <R> Stream<R> flatMap(Functi ...
- git报错解决,warning: could not find UI helper 'git-credential-manager-ui'
在克隆远程代码时,可能遇到这样的报错 warning: could not find UI helper 'git-credential-manager-ui' 这样的报错经常会在我们换了一台电脑或者 ...
- CMU DLSys 课程笔记 2 - ML Refresher / Softmax Regression
CMU DLSys 课程笔记 2 - ML Refresher / Softmax Regression 本节 Slides | 本节课程视频 这一节课是对机器学习内容的一个复习,以 Softmax ...
- 升级高版本springboot2.6.x:org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
升级springboot高版本2.6.x 项目使用到了springcloud的oauth2依赖,直接升级springboot项目版本为最新 2.6.8(2022年6月16日)将会报以下错误: org/ ...
- MySQL 的开窗函数
开窗函数 (Window Function)提供了行集之间的计算能力,在现代的主流关系型数据库中,基本都提供了相似的功能,这些功能在一些业务开发的过程中很有用,本文将简要介绍这些常用的开窗函数 ROW ...