Spring Boot使用AOP的正确姿势
一、为什么需要面向切面编程?
面向对象编程(OOP)的好处是显而易见的,缺点也同样明显。当需要为多个不具有继承关系的对象添加一个公共的方法的时候,例如日志记录、性能监控等,如果采用面向对象编程的方法,需要在每个对象里面都添加相同的方法,这样就产生了较大的重复工作量和大量的重复代码,不利于维护。面向切面编程(AOP)是面向对象编程的补充,简单来说就是统一处理某一“切面”的问题的编程思想。如果使用AOP的方式进行日志的记录和处理,所有的日志代码都集中于一处,不需要再每个方法里面都去添加,极大减少了重复代码。
二、Spring AOP术语
通知(Advice)包含了需要用于多个应用对象的横切行为,完全听不懂,没关系,通俗一点说就是定义了“什么时候”和“做什么”。
连接点(Join Point)是程序执行过程中能够应用通知的所有点。
切点(Poincut)是定义了在“什么地方”进行切入,哪些连接点会得到通知。显然,切点一定是连接点。
切面(Aspect)是通知和切点的结合。通知和切点共同定义了切面的全部内容——是什么,何时,何地完成功能。
引入(Introduction)允许我们向现有的类中添加新方法或者属性。
织入(Weaving)是把切面应用到目标对象并创建新的代理对象的过程,分为编译期织入、类加载期织入和运行期织入。
三、Spring Boot AOP实战
3.1 引入依赖
Spring Boot使用AOP需要添加spring-boot-starter-aop依赖,如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
不需要再添加aspectjweaver的依赖了,因为spring-boot-starter-aop包含了aspectjweaver,并且版本是较新的版本,如果在添加老版本(如1.5.4)启动会报错。
3.2 编写用于拦截的bean
直接定义一个controller,代码如下:
@RestController
public class AopController {
@RequestMapping("/hello")
public String sayHello(){
System.out.println("hello");
return "hello";
}
}
3.3 定义切面
Spring采用@AspectJ注解对POJO进行标注,该注解表明该类不仅仅是一个POJO,还是一个切面。切面是切点和通知的结合,那么定义一个切面就需要编写切点和通知。在代码中,只需要添加@Aspect注解即可。
3.3.1 定义切点
切点是通过@Pointcut注解和切点表达式定义的。
@Pointcut注解可以在一个切面内定义可重用的切点。
由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且实际中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如图是execution表达式的语法:
execution表示在方法执行的时候触发。以“”开头,表明方法返回值类型为任意类型。然后是全限定的类名和方法名,“”可以表示任意类和任意方法。对于方法参数列表,可以使用“..”表示参数为任意类型。如果需要多个表达式,可以使用“&&”、“||”和“!”完成与、或、非的操作。
3.3.2 定义通知
通知有五种类型,分别是:
前置通知(@Before):在目标方法调用之前调用通知
后置通知(@After):在目标方法完成之后调用通知
环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法
返回通知(@AfterReturning):在目标方法成功执行之后调用通知
异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知
代码中定义了三种类型的通知,使用@Before注解标识前置通知,打印“beforeAdvice...”,使用@After注解标识后置通知,打印“AfterAdvice...”,使用@Around注解标识环绕通知,在方法执行前和执行之后分别打印“before”和“after”。这样一个切面就定义好了,代码如下:
@Aspect
@Component
public class AopAdvice {
@Pointcut("execution (* com.shangguan.aop.controller.*.*(..))")
public void test() {
}
@Before("test()")
public void beforeAdvice() {
System.out.println("beforeAdvice...");
}
@After("test()")
public void afterAdvice() {
System.out.println("afterAdvice...");
}
@Around("test()")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("before");
try {
proceedingJoinPoint.proceed();
} catch (Throwable t) {
t.printStackTrace();
}
System.out.println("after");
}
}
3.4 启动测试
完成之后的代码结构如图所示:
运行AopApplication,在浏览器访问http://localhost:8080/hello,不出意外,控制台输出如图所示:
Spring Boot使用AOP的正确姿势的更多相关文章
- spring boot 使用 AOP 的正确姿势 --- 心得
1.前言 向spring boot转型,所有的配置基本上是用注解完成 ,以前使用spring MVC 需要写一大堆xml文件来配置. 基本上没什么变化,但是有些地方需要注意: 环绕通知不要使用异常捕获 ...
- spring boot 中AOP的使用
一.AOP统一处理请求日志 也谈AOP 1.AOP是一种编程范式 2.与语言无关,是一种程序设计思想 面向切面(AOP)Aspect Oriented Programming 面向对象(OOP)Obj ...
- Spring Boot学习——AOP编程的简单实现
首先应该明白一点,AOP是一种编程范式,是一种程序设计思想,与具体的计算机编程语言无关,所以不止是Java,像.Net等其他编程语言也有AOP的实现方式.AOP的思想理念就是将通用逻辑从业务逻辑中分离 ...
- spring boot使用AOP切面编程
spring boot使用AOP 1.在pom文件中添加依赖: <!--spring boot aop切面--> <dependency> <groupId>org ...
- Spring Boot 使用 Aop 实现日志全局拦截
前面的章节我们学习到 Spring Boot Log 日志使用教程 和 Spring Boot 异常处理与全局异常处理,本章我们结合 Aop 面向切面编程来实现全局拦截异常并记录日志. 在 Sprin ...
- spring boot+自定义 AOP 实现全局校验
最近公司重构项目,重构为最热的微服务框架 spring boot, 重构的时候遇到几个可以统一处理的问题,也是项目中经常遇到,列如:统一校验参数,统一捕获异常... 仅凭代码 去控制参数的校验,有时候 ...
- Spring Boot 使用 AOP 实现页面自适应
鉴于复杂页面自适应的难度,一般会做几套模板分别适应手机.平板.电脑等设备.使用 Spring Boot 开发单体应用时,一般会使用 Thymeleaf 模板,那么可以使用 AOP 技术来实现页面自适应 ...
- Spring Boot使用AOP在控制台打印请求、响应信息
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等. AOP简介 AOP全称Aspect Oriented Programming,面向切面,AOP主要实现的 ...
- Spring Boot系列——AOP配自定义注解的最佳实践
AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...
随机推荐
- 【故障公告】阿里云 RDS 实例 CPU 100% 故障引发全站无法正常访问
非常抱歉,今天凌晨 3:20~8:30 左右,我们使用的阿里云 RDS 实例 SQL Server 2016 标准版突然出现 CPU 100% 故障,造成全站无法正常访问,由此给您带来巨大的麻烦,请您 ...
- 云服务器终端命令显示-bash-4.2#怎么解决
原因:删除了root/.bashrc 和 root/.bash_profile两个文件的丢失 解决办法: -bash-4.2# cp /etc/skel/.bashrc /root/ -bash-4. ...
- Flask-install-python2.6
命令: # 安装virtualenv $ sudo yum install python-setuptools $ sudo easy_install virtualenv OR sudo pip i ...
- Python实用笔记 (24)面向对象高级编程——使用@property
这显然不合逻辑.为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数: clas ...
- Electron: 如何以 Vue.js, Vuetify 开始应用
Electron: 使用 JavaScript, HTML 和 CSS 等 Web 技术创建原生程序的框架 Vue.js: Web 前端用于构建用户界面的渐进式框架 Vuetify: Vue.js 的 ...
- Fiddler和JMeter测试需要主要的地方
Fiddler里面设置请求头的时候ContentType和Content-Type这两种写法都可以: 这两种写法都可以. 但是在JMeter中必须要用Content-Type才行,如下图所示: (完)
- Volatile关键字的解读
原子性 定义: 在Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行. Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围 ...
- css样式大全,完整的Css样式大全(整理)
CSS样式被称为为“层叠样式表”,是一种网页制作做不可或缺的技术,是用于装饰网页,达到设计效果的一种样式语言,下面将整理一下css常用样式: 字体属性:(font) 大小 {font-size: x- ...
- zookeeper3.5.5 centos7 完全分布式 搭建随记
zookeeper3.5.5 centos7 完全分布式 搭建随记 这里是当初在三个ECS节点上搭建hadoop+zookeeper+hbase+solr的主要步骤,文章内容未经过润色,请参考的同学搭 ...
- [JAVA]解决不同浏览器下载附件的中文名乱码问题
附件下载时,遇到中文附件名的兼容性问题,firefox.chrome.ie三个派系不兼容,通过分析整理,总结出处理该问题的办法,记录如下: 1.文件名编码 服务器默认使用的是ISO8859-1,而我们 ...