1. 概述

1.1 术语

Spring AOP 的相关术语:

  • Aspect:切面,由一系列切点、增强和引入组成的模块对象,可定义优先级,从而影响增强和引入的执行顺序。事务管理(Transaction management)在java企业应用中就是一个很好的切面样例。
  • Join point:接入点,程序执行期的一个点,例如方法执行、类初始化、异常处理。 在Spring AOP中,接入点始终表示方法执行。
  • Advice:增强,切面在特定接入点的执行动作,包括 "around," "before" and "after"等多种类型。包含Spring在内的许多AOP框架,通常会使用拦截器来实现增强,围绕着接入点维护着一个拦截器链。
  • Pointcut:切点,用来匹配特定接入点的谓词(表达式),增强将会与切点表达式产生关联,并运行在任何切点匹配到的接入点上。通过切点表达式匹配接入点是AOP的核心,Spring默认使用AspectJ的切点表达式。
  • Introduction:引入,为某个type声明额外的方法和字段。Spring AOP允许你引入任何接口以及它的默认实现到被增强对象上。
  • Target object:目标对象,被一个或多个切面增强的对象。也叫作被增强对象。既然Spring AOP使用运行时代理(runtime proxies),那么目标对象就总是代理对象。
  • AOP proxy:AOP代理,为了实现切面功能一个对象会被AOP框架创建出来。在Spring框架中AOP代理的默认方式是:有接口,就使用基于接口的JDK动态代理,否则使用基于类的CGLIB动态代理。但是我们可以通过设置proxy-target-class="true",完全使用CGLIB动态代理。
  • Weaving:织入,将一个或多个切面与类或对象链接在一起创建一个被增强对象。织入能发生在编译时 (compile time )(使用AspectJ编译器),加载时(load time),或运行时(runtime) 。Spring AOP默认就是运行时织入,可以通过枚举AdviceMode来设置。

1.2 简述

本次 Spring AOP 执行顺序主要是针对同一切入点的不同切面执行顺序。

Spring AOP 为定义切面的执行顺序提供了两种方案:

  • 实现 Ordered 接口
  • 使用 @Order 接口

2. 示例

2.1 实现 Ordered 接口

注解类

First

@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RUNTIME)
public @interface First {
}

Sencod

@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RUNTIME)
public @interface Second {
}

切面

FirstAspect

@Slf4j
@Component
@Aspect
public class FirstAspect implements Ordered { @Pointcut("@annotation(com.booleandev.data.aop.First) || @within(com.booleandev.data.aop.First)")
public void pointcut() {
} @Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) {
log.info("--------------> ann,first注解执行"); try {
return pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
} @Override
public int getOrder() {
return 1;
}
}

Second

@Slf4j
@Component
@Aspect
public class SecondAspect implements Ordered{ @Pointcut("@annotation(com.booleandev.data.aop.Second) || @within(com.booleandev.data.aop.Second)")
public void pointcut() {
} @Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) {
log.info("--------------> ann,Second执行"); try {
return pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
} @Override
public int getOrder() {
return 2;
}
}

切入点

@Slf4j
@Service
public class UserService{ @Autowired
private UserRepository userRepository; @First
@Second
public List<User> findAll() {
log.info(entityManager.toString());
return userRepository.findAll();
}
}

结果

--------------> ann,first注解执行
--------------> ann,Second执行

2.2 使用 @Order 接口

注解类

First

@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RUNTIME)
public @interface First {
}

Sencod

@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RUNTIME)
public @interface Second {
}

切面

FirstAspect

@Slf4j
@Component
@Aspect
@Order(1)
public class FirstAspect { @Pointcut("@annotation(com.booleandev.data.aop.First) || @within(com.booleandev.data.aop.First)")
public void pointcut() {
} @Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) {
log.info("--------------> ann,first注解执行"); try {
return pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
} }

SecondAspect

@Slf4j
@Component
@Aspect
@Order(2)
public class SecondAspect{ @Pointcut("@annotation(com.booleandev.data.aop.Second) || @within(com.booleandev.data.aop.Second)")
public void pointcut() {
} @Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) {
log.info("--------------> ann,Second执行"); try {
return pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
} }

切入点

@Slf4j
@Service
public class UserService{ @Autowired
private UserRepository userRepository; @First
@Second
public List<User> findAll() {
log.info(entityManager.toString());
return userRepository.findAll();
}
}

结果

--------------> ann,Second执行
--------------> ann,first注解执行

3. 结论

  • 切面执行顺序有两种方式

    • 实现 Ordered 接口
    • 使用 @Order注解
  • 排序为顺序,数字越小,越先被执行
  • 如果同时使用了注解和实现接口,则以接口的 order 为主

参考文档:

https://juejin.im/post/6844903969433583624

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#aop-ataspectj-advice-ordering

Spring AOP 切面执行顺序的更多相关文章

  1. Spring Aop的执行顺序

    Spring Aop的执行顺序 首先回忆一下 AOP 的常用注解 @Before:前置通知:目标方法之前执行 @After:后置通知:目标方法之后执行 @AfterReturning:返回后通知:执行 ...

  2. 【线上排查实战】AOP切面执行顺序你真的了解吗

    前言 忙,是我这个月的主旋律,也是我频繁鸽文章的接口----蛮三刀把刀 公司这两个月启动了全新的项目,项目排期满满当当,不过该学习还是要学习.这不,给公司搭项目的时候,踩到了一个Spring AOP的 ...

  3. Spring AOP 切面编程记录日志和接口执行时间

    最近客户现在提出系统访问非常慢,需要优化提升访问速度,在排查了nginx.tomcat内存和服务器负载之后,判断是数据库查询速度慢,进一步排查发现是因为部分视图和表查询特别慢导致了整个系统的响应时间特 ...

  4. 利用Spring AOP切面对用户访问进行监控

    开发系统时往往需要考虑记录用户访问系统查询了那些数据.进行了什么操作,尤其是访问重要的数据和执行重要的操作的时候将数记录下来尤显的有意义.有了这些用户行为数据,事后可以以用户为条件对用户在系统的访问和 ...

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

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

  6. spring AOP(切面) 表达式介绍

    在 spring AOP(切面) 例子基础上对表达式进行介绍 1.添加接口删除方法 2.接口实现类 UserDaoServer 添加实现接口删除方法 3.测试类调用delUser方法 4. 输出结果截 ...

  7. 使用Spring AOP切面解决数据库读写分离

    http://blog.jobbole.com/103496/ 为了减轻数据库的压力,一般会使用数据库主从(master/slave)的方式,但是这种方式会给应用程序带来一定的麻烦,比如说,应用程序如 ...

  8. 浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

    简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...

  9. Spring AOP 切面编程的方法

    spring aop的使用分为两种,一种是使用注解来实现,一种是使用配置文件来实现. 先来简单的介绍一下这两种方法的实现,接下来详细的介绍各处的知识点便于查阅.目录如下: 1.基于注解实现spring ...

  10. Spring系列26:Spring AOP 通知与顺序详解

    本文内容 如何声明通知 如何传递参数到通知方法中 多种通知多个切面的通知顺序 多个切面通知的顺序源码分析与图解 声明通知 Spring中有5种通知,通过对应的注解来声明: @BeforeBefore ...

随机推荐

  1. 来个好玩的,用手机随时随地指挥你的 Cursor!

    告别束缚,用手机随时随地指挥你的 Cursor! 嘿,各位 Cursor 的忠实用户和效率达人们! 你是否曾经遇到过这样的场景:人不在Mac旁边,却突然灵感迸发,想要让 Cursor 帮你写点代码.整 ...

  2. centos8安装部署RADIUS+MySQLPGSQL高可用架构实现

    以下是针对中大型网络的 RADIUS+MySQL/PGSQL高可用方案 的完整实现,包含数据库集成.主备集群部署和Keepalived配置: 一.MySQL/PGSQL数据库集成(以MySQL为例) ...

  3. React-Native开发鸿蒙NEXT-cookie设置

    React-Native开发鸿蒙NEXT-cookie设置 应用有个积分商城,做一些积分兑换的业务,就一个基于react-native-webview开发的页面,在页面加载的时候通过js注入来设置co ...

  4. cmake基础知识

    Cmake Cmake变量 Cmake的基本类型只有两种,分别是字符串和字符串列表,使用set命令来设置变量 set(var abc) # abc是字符串,var是值为"abc"的 ...

  5. 关于cc1链-lazymap版复现

    关于cc1链-lazymap版复现 思路,在cc链中最重要的其实是transform方法;其反射调用执行的性质+transformchain性质,导致可以通过构造反射调用链子,也就是Runtime.e ...

  6. python爬虫学习——re模块(正则表达式)

    正则表达式常用操作符 . 任何单个字符 [] 字符集,对单个字符给出取值范围 [abc].[a-z] [^ ] 非字符集,对单个字符给出排除范围 [^abc] * 对前一个字符0次或无限次拓展 abc ...

  7. 关于Node.js 构建中遇到node-gyp报错问题的解决方案记录

    项目今天进行版本更新,在走阿里云流水线的时候,出现了Node.js 构建过程报错问题,抱歉详情截图如下: 经过反复排查,最终发现是因为阿里云的npm仓库的问题,于是果断更换npm仓库,执行命令如下: ...

  8. 多多行动,Action And Think Not Thinking Thinking But Not Action

    行动和思考 为什么道理大家都懂,还是过不好我们自己的生活呢? 其实从小到大,我们了解和接触的大道理以及理论知识已经很多了,很多高深的哲学思想,有可能在我们小学的时候已经接触到了.种瓜得瓜,种豆得豆.一 ...

  9. DotTrace系列:1. 理解四大经典的诊断类型(上)

    一:背景 1. 讲故事 在所有与 .NET相关的JetBrains产品中,我觉得 DotTrace 是最值得深入学习和研究的一款,个人觉得它的优点如下: 跨平台诊断 (Windows,Linux,Ma ...

  10. 一文了解:仿真技术的巨头——美国Altair公司

    Altair公司成立于1967年,总部位于美国马里兰州巴尔的摩,在全球拥有近35000名员工,是一家世界领先的软件公司,在汽车.航空航天.军工和建筑等领域拥有广泛的产品和解决方案. Altair公司主 ...