首页 > 其他分享 >Spring AOP 切面执行顺序

Spring AOP 切面执行顺序

时间:2024-07-12 10:43:29浏览次数:17  
标签:return Spring Second 切面 AOP public

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

标签:return,Spring,Second,切面,AOP,public
From: https://www.cnblogs.com/booleandev/p/18297799/spring-aop-surface-execution-order-wv5xf

相关文章

  • Java毕业设计基于Vue+SpringBoot的电影院订票选座管理系统(代码+数据库+文档LW+运行成
    很多朋友发现后期找不到文章,收藏关注不迷路文章目录项目介绍技术介绍项目界面关键代码目录项目介绍在飞速发展的今天,网络已成为人们重要的交流平台。电影院每天都有大量的需要通过网络发布,为此,本人开发了一个基于B/S;浏览器/服务器;模式的电影院管理系统。该系......
  • Java毕业设计基于Vue+SpringBoot的畅游游戏销售平台(代码+数据库+文档LW+运行成功)
    很多朋友发现后期找不到文章,收藏关注不迷路文章目录项目介绍技术介绍项目界面关键代码目录项目介绍近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,畅游游戏销售平台利用计算机网络实现信息化管理,使整个畅游游戏销售平......
  • Java毕业设计基于Vue+SpringBoot的爱看漫画小程序(代码+数据库+文档LW+运行成功)
    很多朋友发现后期找不到文章,收藏关注不迷路文章目录项目介绍技术介绍项目界面关键代码目录项目介绍相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低爱看漫画的运营人员成本,实现了爱看漫画的标准化、制度化、程序化的管理,有效地防止了爱看漫画的随意管......
  • 使用Spring Boot集成Elasticsearch
    使用SpringBoot集成Elasticsearch大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!Elasticsearch是一个分布式搜索和分析引擎,特别适用于处理海量数据。本文将详细介绍如何在SpringBoot项目中集成Elasticsearch,包括环境配置、基本CRUD操作和常见问题的解......
  • 使用Spring Boot实现任务调度
    使用SpringBoot实现任务调度大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在日常开发中,任务调度是一个非常常见的需求,例如定时清理日志、定时备份数据、定时发送通知等。SpringBoot提供了强大的任务调度功能,可以方便地实现定时任务。本文将详细介绍如......
  • 使用Spring Boot实现文件上传功能
    使用SpringBoot实现文件上传功能大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在这篇文章中,我们将详细介绍如何使用SpringBoot实现文件上传功能。这是一个常见的需求,无论是处理用户上传的图片、文档,还是其他类型的文件,了解并掌握文件上传的实现是非常......
  • 基于java+springboot+vue实现的在线教育系统(文末源码+Lw)111
    基于SpringBoot+Vue的实现的在线教育系统(源码+数据库+万字Lun文+流程图+ER图+结构图+演示视频+软件包)系统功能:本在线教育系统管理员功能有个人中心,用户管理,讲师管理,普通管理员管理,课程管理员管理,课程管理,课程分类管理,教师管理,名师管理,系统管理,订单管理。普通管理员和课程......
  • 基于java+springboot+vue实现的作业管理系统(文末源码+Lw)110
    基于SpringBoot+Vue的实现的作业管理系统(源码+数据库+万字Lun文+流程图+ER图+结构图+演示视频+软件包)功能描述:作业管理系统有管理员,教师,学生三个角色。教师和学生都可以进行注册然后再登录。学生可以修改自己的密码,查看和下载作业信息,并且可以提交自己写好的作业,并且可以......
  • SpringBoot2.6.13版本引入Swagger
    1.引入依赖<!--https://mvnrepository.com/artifact/io.springfox/springfox-swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>3.0.0</version&g......
  • 缓存框架-Spring Cache基本用法
    一、概述SpringCache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。SpringCache提供了一层抽象,底层可以切换不同的缓存实现,例如:EHCacheCaffeineRedis(常用)二、环境准备1、导入Redis和SpringCache依赖<dependency><groupId......