【Spring注解驱动开发】你敢信?面试官竟然让我现场搭建一个AOP测试环境!

简介: 金九银十的跳槽黄金期已拉开序幕,相信很多小伙伴也在摩拳擦掌,想换一个新的工作环境。然而,由于今年疫情的影响,很多企业对于招聘的要求是越来越严格。之前,很多不被问及的知识点,最近面试时都会被问到了。这不,有些面试官竟然让面试者现场搭建一个AOP测试环境。那怎么办呢?那就给他搭建一个呗!

什么是AOP?


AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。

比如,在《Spring实战(第4版)》中有如下一张图描述了AOP的大体模型。

从这张图中,我们可以看出:所谓切面,相当于应用对象间的横切点,我们可以将其单独抽象为单独的模块。

总之一句话:AOP是指在程序的运行期间动态的将某段代码切入到指定方法、指定位置进行运行的编程方式。AOP的底层是使用动态代理实现的。

搭建环境


1.导入AOP依赖

要想搭建AOP环境,首先,我们就需要在项目的pom.xml文件中引入AOP的依赖,如下所示。

<properties>
    <spring.version>5.2.6.RELEASE</spring.version>
</properties>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring.version}</version>
</dependency>

2.定义目标类

io.mykit.spring.plugins.register.aop包下创建一个MathHandler类,用于处理数学计算上的一些逻辑。比如,我们在MathHandler类中定义了一个加法操作,返回两个整数类型值的和,如下所示。

package io.mykit.spring.plugins.register.aop;
/**
 * @author binghe
 * @version 1.0.0
 * @description 定义一个数据处理器类,用于测试AOP
 */
public class MathHandler {
    public int add(int i, int j){
        System.out.println("目标方法执行");
        return i + j;
    }
}

3.定义切面类

io.mykit.spring.plugins.register.aspect包下创建一个LogAspect切面类,在LogAspect类中定义了几个打印日志的方法,以这些方法来感知MathHandler类中的add()方法的运行情况。如果需要切面类来感知目标类方法的运行情况,则需要使用Spring AOP中的通知方法。

AOP中的通知方法及其注解与含义如下:

  • 前置通知(@Before):在目标方法运行之前运行。
  • 后置通知(@After):在目标方法运行结束之后运行,不管是正常结束还是异常结束都会执行。
  • 返回通知(@AfterReturning):在目标方法正常返回之后运行。
  • 异常通知(@AfterThrowing):在目标方法抛出异常后运行。
  • 环绕通知(@Around):动态代理,手动推进目标方法运行。

综上,LogAspect类中的具体方法定义如下所示。

package io.mykit.spring.plugins.register.aspect;
import org.aspectj.lang.annotation.*;
/**
 * @author binghe
 * @version 1.0.0
 * @description 打印日志的切面类
 */
@Aspect
public class LogAspect {
    @Pointcut("execution(public int io.mykit.spring.plugins.register.aop.MathHandler.*(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void logStart(){
        System.out.println("加法运行开始,参数列表是:{}");
    }
    @After("pointCut()")
    public void logEnd(){
        System.out.println("加法运行结束");
    }
    @AfterReturning("pointCut()")
    public void logReturn(){
        System.out.println("加法正常返回,运行结果:{}");
    }
    @AfterThrowing("pointCut()")
    public void logException(){
        System.out.println("加法异常,异常信息:{}");
    }
}
  • logStart()方法:MathHandler类的add()方法运行之前运行。
  • logEnd()方法:MathHandler类的add()方法运行结束之后运行。
  • logReturn()方法:MathHandler类的add()方法正常返回之后运行。
  • logException()方法:MathHandler类的add()方法抛出异常后执行。

4.将目标类和切面类加入到IOC容器

io.mykit.spring.plugins.register.config包中,新建AopConfig类,并使用@Configuration注解标注这是一个Spring的配置类,同时使用@EnableAspectJAutoProxy注解开启基于注解的AOP模式。在AopConfig类中,使用@Bean注解将MathHandler类和LogAspect类加入到IOC容器中,如下所示。

package io.mykit.spring.plugins.register.config;
import io.mykit.spring.plugins.register.aop.MathHandler;
import io.mykit.spring.plugins.register.aspect.LogAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
 * @author binghe
 * @version 1.0.0
 * @description 测试AOP
 */
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
    @Bean
    public MathHandler mathHandler(){
        return new MathHandler();
    }
    @Bean
    public LogAspect logAspect(){
        return new LogAspect();
    }
}

5.创建测试类

io.mykit.spring.test包中创建AopTest测试类,并在AopTest类中创建testAop01()方法,如下所示。

package io.mykit.spring.test;
import io.mykit.spring.plugins.register.aop.MathHandler;
import io.mykit.spring.plugins.register.config.AopConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * @author binghe
 * @version 1.0.0
 * @description 测试切面
 */
public class AopTest {
    @Test
    public void testAop01(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
        MathHandler mathHandler = context.getBean(MathHandler.class);
        mathHandler.add(1, 2);
        context.close();
    }
}

运行AopTest类中的testAop01()方法,输出的结果信息如下所示。

加法运行开始,参数列表是:{}
目标方法执行
加法运行结束
加法正常返回,运行结果:{}

可以看到,执行了切面类中的方法,并打印出了相关信息。但是没有打印参数列表和运行结果。

6.在切面类中打印参数列表和返回结果

那如果需要打印出参数列表和运行结果,该怎么办呢?别急,我们继续往下看。

要想打印出参数列表和运行结果,就需要对LogAspect类中的方法进行优化,优化后的结果如下所示。

package io.mykit.spring.plugins.register.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import java.util.Arrays;
/**
 * @author binghe
 * @version 1.0.0
 * @description 打印日志的切面类
 */
@Aspect
public class LogAspect {
    @Pointcut("execution(public int io.mykit.spring.plugins.register.aop.MathHandler.*(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName() + " 运行开始,参数列表是:{"+ Arrays.asList(joinPoint.getArgs()) +"}");
    }
    @After("pointCut()")
    public void logEnd(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName() + " 运行结束");
    }
    @AfterReturning(value = "pointCut()", returning = "result")
    public void logReturn(JoinPoint joinPoint, Object result){
        System.out.println(joinPoint.getSignature().getName() + " 正常返回,运行结果:{"+result+"}");
    }
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void logException(JoinPoint joinPoint, Exception exception){
        System.out.println(joinPoint.getSignature().getName() + " 异常,异常信息:{"+exception+"}");
    }
}

这里,需要注意的是:JoinPoint参数一定要放在参数的第一位。

此时,我们再次运行AopTest类中的testAop01()方法,输出的结果信息如下所示。

add 运行开始,参数列表是:{[1, 2]}
目标方法执行
add 运行结束
add 正常返回,运行结果:{3}

7.目标方法抛出异常

我们在MathHandler类的add()方法中抛出一个异常,来测试下异常情况,如下所示。

package io.mykit.spring.plugins.register.aop;
/**
 * @author binghe
 * @version 1.0.0
 * @description 定义一个数据处理器类,用于测试AOP
 */
public class MathHandler {
    public int add(int i, int j){
        System.out.println("目标方法执行");
        throw new RuntimeException();
       //return i + j;
    }
}

此时,我们再次运行AopTest类中的testAop01()方法,输出的结果信息如下所示。

add 运行开始,参数列表是:{[1, 2]}
目标方法执行
add 运行结束
add 异常,异常信息:{java.lang.RuntimeException}

可以看到,正确的输出了切面中打印的信息。

至此,我们的AOP测试环境就搭建成功了。


相关文章
|
8月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
789 0
|
机器学习/深度学习 人工智能 并行计算
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
|
8月前
|
存储 测试技术 API
数据驱动开发软件测试脚本
今天刚提交了我的新作《带着ChatGPT玩转软件开发》给出版社,在写作期间跟着ChatGPT学到许多新知识。下面分享数据驱动开发软件测试脚本。
334 0
|
11月前
|
传感器 人工智能 JavaScript
鸿蒙开发:DevEcoTesting中的稳定性测试
DevEcoTesting主要的目的也是用于软件的测试,可以让开发者无需复杂的配置,即可一键执行测试任务,同时提供了测试报告和分析,无论是对于开发者还是测试同学来说,都是一个非常方便的工具。
340 3
鸿蒙开发:DevEcoTesting中的稳定性测试
|
10月前
|
敏捷开发 运维 数据可视化
DevOps看板工具中的协作功能:如何打破开发、测试与运维之间的沟通壁垒
在DevOps实践中,看板工具通过可视化任务管理和自动化流程,提升开发与运维团队的协作效率。它支持敏捷开发、持续交付,助力团队高效应对需求变化,实现跨职能协作与流程优化。
|
10月前
|
运维 jenkins 测试技术
"还在苦等开发部署环境?3步教你用Jenkins拿回测试主动权"
测试工程师最头疼的问题是什么?依赖开发部署环境! 开发延期→测试时间被压缩→紧急上线后BUG频出→测试背锅。传统流程中,测试被动等待部署,效率低下。而Jenkins自动化部署让测试人员自主搭建环境,实现: ✅ 随时触发测试,不再苦等开发 ✅ 部署效率提升10倍,抢回测试时间 ✅ 改善团队协作,减少互相甩锅 学习Jenkins部署能力,成为高效测试工程师,告别被动等待!
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4ASK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的4ASK调制解调系统的硬件测试版本,该系统包括testbench、高斯信道模块和误码率统计模块,并新增了ILA在线数据采集和VIO在线SNR设置功能。通过VIO设置不同SNR(如15dB和25dB),实现了对系统性能的实时监测与调整。4ASK是一种通过改变载波幅度表示数据的数字调制方式,适用于多种通信场景。FPGA平台的高效性和灵活性使其成为构建高性能通信系统的理想选择。
378 17
|
10月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
1362 0
|
11月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
1208 0
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
539 0