spring---面向切面(AOP @Pointcut 注解篇)
2.1 第一个实例
接下来,我们先看一个极简的例子:所有的get请求被调用前在控制台输出一句"get请求的advice触发了"。
具体实现如下:
1、创建一个AOP切面类,只要在类上加个 @Aspect 注解即可。@Aspect 注解用来描述一个切面类,定义切面类的时候需要打上这个注解。@Component 注解将该类交给 Spring 来管理。在这个类里实现advice:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* @Description:
* @author: 张重虎
* @Date: 2022/2/8 17:02
* @Version 1.0
*/
@Aspect
@Component
public class LogAdvice {
/**
* 定义一个切点:所有被 GetMapping 注解修饰的方法都会被织入 advice
*/
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
private void logAdvicePointcut(){}
/**
* 表示 logAdvice 将在目标方法执行前执行
*/
@Before("logAdvicePointcut()")
public void logAdvice(){
//这里只是一个示例,你可以写任何处理逻辑
System.out.println("切面 @Before 执行了");
}
}
2、创建一个接口类,内部创建一个get请求:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:
* @author: 张重虎
* @Date: 2022/2/8 17:12
* @Version 1.0
*/
@RestController
@RequestMapping(value = "/aop")
public class AopController {
@GetMapping("/getTest")
public JSONObject aopTest() {
System.out.println("Get 方法代码执行中");
return JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200}");
}
@PostMapping("/postTest")
public JSONObject aopTestTwo(){
System.out.println("Post 方法代码执行中");
return JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200}");
}
}
项目启动后,Get 方式请求http://localhost:8080/aop/getTest接口:

Post 方式请求http://localhost:8080/aop/postTest接口,控制台无输出,证明切点确实是只针对被GetMapping修饰的方法。
2.2 第二个实例
下面我们将问题复杂化一些,该例的场景是:
1、 自定义一个注解PermissionsAnnotation
2、 创建一个切面类,切点设置为拦截所有标注PermissionsAnnotation的方法,截取到接口的参数,进行简单的权限校验
3、 将PermissionsAnnotation标注在测试接口类的测试接口test上
具体的实现步骤:
1、 使用@Target、@Retention、@Documented自定义一个注解:
import java.lang.annotation.*;
/**
* @Description: 自定义注解
* @author: 张重虎
* @Date: 2022/2/8 17:29
* @Version 1.0
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PermissionAnnotation {
}
2、创建第一个AOP切面类,,只要在类上加个 @Aspect 注解即可。@Aspect 注解用来描述一个切面类,定义切面类的时候需要打上这个注解。@Component 注解将该类交给 Spring 来管理。在这个类里实现第一步权限校验逻辑:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* @Description:
* @author: 张重虎
* @Date: 2022/2/8 17:53
* @Copyright: Xi'an Dian Tong Software Co., Ltd. All Rights Reserved.
* @Version 1.0
*/
@Aspect
@Component
@Order(1)
public class PermissionFirstAdvice {
@Pointcut("@annotation(com.example.zhangchonghu.demo.controller.aop3.PermissionAnnotation)")
private void permissionCheck(){}
@Around("permissionCheck()")
public Object permissionCheckFirst(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("===================第一个切面===================:" + System.currentTimeMillis());
//获取请求参数,详见接口类
Object[] objects = joinPoint.getArgs();
Long id = ((JSONObject) objects[0]).getLong("id");
String name = ((JSONObject) objects[0]).getString("name");
System.out.println("id1->>>>>>>>>>>>>>>>>>>>>>" + id);
System.out.println("name1->>>>>>>>>>>>>>>>>>>>>>" + name);
// id小于0则抛出非法id的异常
if (id < 0) {
return JSON.parseObject("{\"message\":\"illegal id\",\"code\":403}");
}
return joinPoint.proceed();
}
}
3、创建接口类,并在目标方法上标注自定义注解 PermissionsAnnotation:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:
* @author: 张重虎
* @Date: 2022/2/8 17:58
* @Copyright: Xi'an Dian Tong Software Co., Ltd. All Rights Reserved.
* @Version 1.0
*/
@RestController
@RequestMapping("/permission")
public class TestController {
@RequestMapping(value = "/check", method = RequestMethod.POST)
// 添加自定义注解
@PermissionAnnotation()
public JSONObject getGroupList(@RequestBody JSONObject request) {
System.out.println("方法中打印请求参数"+request);
return JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200}");
}
}
有人会问,如果我一个接口想设置多个切面类进行校验怎么办?这些切面的执行顺序如何管理?
很简单,一个自定义的AOP注解可以对应多个切面类,这些切面类执行顺序由@Order注解管理,该注解后的数字越小,所在切面类越先执行。
下面在实例中进行演示:
创建第二个AOP切面类,在这个类里实现第二步权限校验:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* @Description:
* @author: 张重虎
* @Date: 2022/2/8 18:07
* @Version 1.0
*/
@Aspect
@Component
@Order(0)
public class PermissionSecondAdvice {
/**
* 自定义注解作为切面,凡是被这个注解定义的方法,都会被切面拦截
*/
@Pointcut("@annotation(com.example.zhangchonghu.demo.controller.aop3.PermissionAnnotation)")
private void permissionCheck(){}
@Around("permissionCheck()")
public Object permissionCheckSecond(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("===================第二个切面===================:" + System.currentTimeMillis());
//获取请求参数,详见接口类
Object[] objects = joinPoint.getArgs();
Long id = ((JSONObject) objects[0]).getLong("id");
String name = ((JSONObject) objects[0]).getString("name");
System.out.println("id->>>>>>>>>>>>>>>>>>>>>>" + id);
System.out.println("name->>>>>>>>>>>>>>>>>>>>>>" + name);
// name不是管理员则抛出异常
if (!"admin".equals(name)) {
return JSON.parseObject("{\"message\":\"not admin\",\"code\":403}");
}
return joinPoint.proceed();
}
}
重启项目,继续测试,构造两个参数都异常的情况:

响应结果,表面第二个切面类执行顺序更靠前:

2.3 总结
@Pointcut 注解,用来定义一个切面,即上文中所关注的某件事情的入口,切入点定义了事件触发时机。
@Pointcut 注解指定一个切面,定义需要拦截的东西,这里介绍两个常用的表达式:一个是使用 execution(),另一个是使用 annotation()。
execution表达式:
@Aspect
@Component
public class LogAspectHandler {
/**
* 定义一个切面,拦截 com.itcodai.course09.controller 包和子包下的所有方法
*/
@Pointcut("execution(* com.mutest.controller..*.*(..))")
public void pointCut() {}
}
以 execution(* * com.mutest.controller...(..))) 表达式为例:
第一个 * 号的位置:表示返回值类型,* 表示所有类型。
包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,在本例中指 com.mutest.controller包、子包下所有类的方法。
第二个 * 号的位置:表示类名,* 表示所有类。
(..):这个星号表示方法名, 表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
annotation() 表达式:
annotation() 方式是针对某个注解来定义切面,比如我们对具有 @PostMapping 注解的方法做切面,可以如下定义切面:
@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
public void annotationPointcut() {}
然后使用该切面的话,就会切入注解是 @PostMapping 的所有方法。这种方式很适合处理 @GetMapping、@PostMapping、@DeleteMapping不同注解有各种特定处理逻辑的场景。
还有就是如上面案例所示,针对自定义注解来定义切面:
@Pointcut("@annotation(com.example.demo.PermissionsAnnotation)")
private void permissionCheck() {}
spring---面向切面(AOP @Pointcut 注解篇)的更多相关文章
- Spring AOP 面向切面编程相关注解
Aspect Oriented Programming 面向切面编程 在Spring中使用这些面向切面相关的注解可以结合使用aspectJ,aspectJ是专门搞动态代理技术的,所以比较专业. ...
- Spring框架使用(控制反转,依赖注入,面向切面AOP)
参见:http://blog.csdn.net/fei641327936/article/details/52015121 Mybatis: 实现IOC的轻量级的一个Bean的容器 Inversion ...
- Spring 面向切面编程(AOP)
Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...
- 快速高效掌握企业级项目中的Spring面向切面编程应用,外带讲面试技巧
Spring面向切面编程(AOP)是企业级应用的基石,可以这样说,如果大家要升级到高级程序员,这部分的知识必不可少. 这里我们将结合一些具体的案例来讲述这部分的知识,并且还将给出AOP部分的一些常见面 ...
- Spring事务管理—aop:pointcut expression 常见切入点表达式及事务说明
Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明 例: <aop:config> <aop:pointcut expression= ...
- spring:AOP面向切面编程(注解)03
使用注解写aop时最好使用环绕通知写 切面类: /** * 用于记录日志的工具类,它里面提供了公共的代码 */ @Component("logger") @Aspect //表示当 ...
- spring面向切面编程示例(xml配置形式vs@注解形式)
一.xml配置形式 1.在Spring配置文件中增加面向切面配置当调用com.activemq.service.impl.ConsumerServiceImpl接口实现类的任意方法时执行切面类中的方法 ...
- 详解Spring面向切面编程(AOP)三种实现
一.什么是AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善. ...
- Spring框架系列(五)--面向切面AOP
背景: 当需要为多个不具有继承关系的对象引入一个公共行为,例如日志.权限验证.事务等功能时,如果使用OOP,需要为每个对象引入这些公共 行为.会产生大量重复代码,并且不利用维护.AOP就是为了解决这个 ...
- Spring——面向切面编程(AOP)详解
声明:本博客仅仅是一个初学者的学习记录.心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流.一起学习.一起进步的朋友可以加我微信Liu__66666666 这是简单学习一遍之 ...
随机推荐
- ENVI大气校正方法反演Landsat 7地表温度
本文介绍基于ENVI软件,实现对Landsat 7遥感影像加以大气校正方法的地表温度反演操作. 目录 1 图像前期处理与本文理论部分 2 实际操作 2.1 植被覆盖度计算 2.2 地表比辐射率计算 2 ...
- LCD与OLED的相爱相杀
目前市面的显示技术主要分为LCD与OLED. 本文主要记录对LCD与OLED的学习. 导言:介绍一些专业名词和术语. 像素点:是指在由一个数字序列表示的图像中的一个最小单位,称为像素. 一张图片在显示 ...
- 关于reids免安装的使用与注意事项
redis是我们现在常用的缓存数据库.可是redis官方网站只提供linux版本,而我们又习惯在windows系统上使用开发工具,这又怎么办呢? 幸好微软官方也提供了windows版本,方便根据实际需 ...
- 【分享】如何才能简洁高效不失优雅的爆破ZIP文件?
0x01 前言 在CTF比赛中,压缩包密码的爆破一直是一个热门话题.在这个过程中,简洁高效的方法是至关重要的.本文将介绍一些实用的技巧和工具,帮助您高效地爆破ZIP文件密码,而不失优雅.我们将探讨一些 ...
- CentOS系统修改yum源
看了一下自己之前写的文章,写的那叫一个垃圾.无地自容.作为一个菜鸡.现在不妨在博客上记录一下自己学习的记录,同时发表出来,也算作是对自己的勉励. 吾辈不孤,吾道不寡,诸君加油! 下面进入正题: Cen ...
- 如何在工作中利用Prompt高效使用ChatGPT?
导读 AI 不是来替代你的,是来帮助你更好工作.用better prompt使用chatgpt,替换搜索引擎,让你了解如何在工作中利用Prompt高效使用ChatGPT. 01背景 现在 GPT 已经 ...
- 【LaTeX】环境配置以及中文支持
目录 网页环境 Overleaf 本地环境 TeX Live TeXstudio VSCode 安装 LaTeX Workshop 扩展 编译链配置 正向同步 反向同步 其他可选配置 中文支持 XeL ...
- [Lua] 实现所有类的基类Object、模拟单继承OO、实现抽象工厂
所有类的基类 Object Lua 没有严格的 oo(Object-Oriented)定义,可以利用元表特性来实现 先定义所有类的基类,即Object类.代码顺序从上到下,自成一体.完整代码 定义一个 ...
- 《Web安全基础》02. 信息收集
@ 目录 1:CDN 绕过 1.1:判断是否有 CDN 服务 1.2:常见绕过方法 1.3:相关资源 2:网站架构 3:WAF 4:APP 及其他资产 5:资产监控 本系列侧重方法论,各工具只是实现目 ...
- 智能AI 的应用场景
小凡智能AI是一款基于人工智能技术开发的助软件,能够帮助用户解决各种各样的问题,提高工作效率和生活质量.它的应用范围广泛,涵盖了工作.学习.健康等多个方面,为用户提供了全方位的服务支持. 在工作方面, ...