文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Aop 常见注解和执行顺序

2024-12-02 07:39

关注

Spring 一开始最强大的就是 IOC / AOP 两大核心功能,我们今天一起来学习一下 Spring AOP 常见注解和执行顺序。Spring Aop 的常用注解

首先我们一起来回顾一下 Spring Aop 中常用的几个注解:

常见问题

1、你肯定知道 Spring  , 那说说 Aop 的去全部通知顺序, Spring Boot 或者 Spring Boot 2 对 aop 的执行顺序影响?

2、说说你在 AOP 中遇到的那些坑?

示例代码

下面我们先快速构建一个 spring aop 的 demo 程序来一起讨论 spring aop 中的一些细节。

配置文件

为了方便我直接使用 spring-boot 进行快速的项目搭建,大家可以使用 idea 的spring-boot 项目快速创建功能,或者去 start.spring.io 上面去快速创建spring-boot 应用。

因为本人经常手动去网上贴一些依赖导致,依赖冲突服务启动失败等一些问题。

plugins {
id 'org.springframework.boot' version '2.6.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group 'io.zhengsh'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
dependencies {
# 其实这里也可以不增加 web 配置,为了试验简单,大家请忽略
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-aop'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}

接口类

首先我们需要定义一个接口。我们这里可以再来回顾一下 JDK 的默认代理实现的选择:

这块的逻辑在 DefaultAopProxyFactory 大家有兴趣可以去看看。

public interface CalcService {
public int div(int x, int y);
}

实现类

这里我门就简单一点做一个除法操作,可以模拟正常也可以很容易的模拟错误。

@Service
public class CalcServiceImpl implements CalcService {
@Override
public int div(int x, int y) {
int result = x / y;
System.out.println("====> CalcServiceImpl 被调用了,我们的计算结果是:" + result);
return result;
}
}

aop 拦截器

申明一个拦截器我们要为当前对象增加 @Aspect 和 @Component ,笔者之前也是才踩过这样的坑,只加了一个。

其实这块我刚开始也不是很理解,但是我看了 Aspect 注解的定义我就清楚了

这里面根本就没有 Bean 的定义。所以我们还是乖乖的加上两个注解。

还有就是如果当测试的时候需要开启Aop 的支持为配置类上增加@EnableAspectJAutoProxy 注解。

其实 Aop 使用就三个步骤:

@Aspect
@Component
public class MyAspect {
@Pointcut("execution(* io.zhengsh.spring.service.impl..*.*(..))")
public void divPointCut() {
}
@Before("divPointCut()")
public void beforeNotify() {
System.out.println("----===>> @Before 我是前置通知");
}
@After("divPointCut")
public void afterNotify() {
System.out.println("----===>> @After 我是后置通知");
}
@AfterReturning("divPointCut")
public void afterReturningNotify() {
System.out.println("----===>> @AfterReturning 我是前置通知");
}
@AfterThrowing("divPointCut")
public void afterThrowingNotify() {
System.out.println("----===>> @AfterThrowing 我是异常通知");
}
@Around("divPointCut")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object retVal;
System.out.println("----===>> @Around 环绕通知之前 AAA");
retVal = proceedingJoinPoint.proceed();
System.out.println("----===>> @Around 环绕通知之后 BBB");
return retVal;
}
}

测试类

其实我这个测试类,虽然用了 @Test 注解,但是我这个类更加像一个 main 方法把:如下所示:

执行结论

结果记录:spring 4.x, spring-boot 1.5.9

无法现在依赖,所以无法试验

我直接说一下结论:Spring 4 中环绕通知是在最里面执行的

结果记录:spring 版本5.3.15 springboot 版本2.6.3

多切面的情况

多个切面的情况下,可以通过@Order指定先后顺序,数字越小,优先级越高。如下图所示:

代理失效场景

下面一种场景会导致 aop 代理失效,因为我们在执行 a 方法的时候其实本质是执行 AServer#a 的方法拦截器(MethodInterceptor)链, 当我们在 a 方法内直接执行b(), 其实本质就相当于 this.b() , 这个时候由执行 a方法是调用到 a 的原始对象相当于是 this 调用,那么会导致 b() 方法的代理失效。这个问题也是我们开发者在开发过程中最常遇到的一个问题。

@Service
public class AService {
public void a() {
System.out.println("...... a");
b();
}
public void b() {
System.out.println("...... b");
}
}


来源:Java知音内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯