当前位置: 首页 > 科技观察

你相信吗?面试官还让我现场搭建AOP测试环境!

时间:2023-03-13 14:40:19 科技观察

作者个人研发在高并发场景下提供了一个简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。开源半年多以来,已成功为十几家中小企业提供精准定时调度解决方案,经受住了生产环境的考验。为了造福更多的童鞋,这里放上开源框架的地址:https://github.com/sunshinelyz/mykit-delay跳槽的黄金期已经拉开序幕。相信很多朋友也是摩拳擦掌。我想换一个新的工作环境。但今年受疫情影响,不少企业对招聘的要求越来越严格。很多以前没有问到的知识点,最近面试都会问到。这不,有些面试官甚至要求面试官现场搭建AOP测试环境。那我们该怎么办呢?那就给他造一个吧!什么是AOP?AOP(AspectOrientProgramming),直译就是面向方面的编程。AOP是一种编程思想,是面向对象编程(OOP)的补充。面向对象编程将程序抽象为各个层次的对象,而面向方面编程将程序抽象为各个方面。比如《Spring实战(第4版)》,下图描述了AOP的一般模型。从这张图我们可以看出,所谓的切面相当于应用对象之间的横切点,我们可以将它抽象成一个单独的模块。一句话概括:AOP是指在程序运行过程中,动态地将某段代码切割成指定的方法和指定的位置的一种编程方式。AOP底层是使用动态代理实现的。搭建环境1.导入AOP依赖要搭建AOP环境,首先我们需要在项目的pom.xml文件中引入AOP依赖,如下图。5.2.6.RELEASEorg.springframeworkspring-aspects${spring.version}2.定义目标类在io.mykit.spring.plugins.register.aop包下创建一个MathHandler类来处理数学计算中的一些逻辑。比如我们在MathHandler类中定义一个加法运算,返回两个整数类型值的和,如下所示。packageio.mykit.spring.plugins.register.aop;/***@authorbinghe*@version1.0.0*@description定义了一个用于测试AOP的数据处理器类*/publicclassMathHandler{publicintadd(inti,intj){System.out.println("目标方法执行");returni+j;}}3.定义切面类在io.mykit.spring.plugins.register.aspect包下创建一个LogAspect切面类,在LogAspect类中定义几个打印日志的方法,用于感知操作MathHandler类中的add()方法。如果需要切面类感知目标类方法的运行,就需要使用SpringAOP中的通知方法。AOP中的通知方法及其注解和含义如下:预通知(@Before):在目标方法运行之前运行。事后通知(@After):在目标方法运行结束后运行,不管是正常结束还是异常结束。返回通知(@AfterReturning):在目标方法正常返回后运行。异常通知(@AfterThrowing):在目标方法抛出异常后运行。环绕通知(@Around):动态代理,手动推进目标方法运行。综上所述,LogAspect类中的具体方法定义如下。packageio.mykit.spring.plugins.register.aspect;importorg.aspectj.lang.annotation.*;/***@authorbinghe*@version1.0.0*@descriptionAspect打印日志类*/@AspectpublicclassLogAspect{@Pointcut("执行(publicintio.mykit.spring.plugins.register.aop.MathHandler.*(..))")publicvoidpointCut(){}@Before("pointCut()")publicvoidlogStart(){System.out.println("加法运算开始,参数列表为:{}");}@After("pointCut()")publicvoidlogEnd(){System.out.println("加法运算结束");}@AfterReturning("pointCut()")publicvoidlogReturn(){System.out.println("加法正常返回,运算结果:{}");}@AfterThrowing("pointCut()")publicvoidlogException(){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容器中,如下图。packageio.mykit.spring.plugins.register.config;importio.mykit.spring.plugins.register.aop.MathHandler;importio.mykit.spring.plugins.register.aspect.LogAspect;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.EnableAspectJAutoProxy;/***@authorbinghe*@version1.0.0*@description测试AOP*/@Configuration@EnableAspectJAutoProxypublicclassAopConfig{@BeanpublicMathHandlermathHandler(){);}@BeanpublicLogAspectlogAspect(){returnnewLogAspect();}}5。创建测试类在io.mykit.spring.test包中创建一个AopTest测试类,在AopTest类中创建一个testAop01()方法,如下图。packageio.mykit.spring.test;importio.mykit.spring.plugins.register.aop.MathHandler;importio.mykit.spring.plugins.register.config.AopConfig;importorg.junit.Test;importorg.springframework.context.annotation。AnnotationConfigApplicationContext;/***@authorbinghe*@version1.0.0*@description测试方面*/publicclassAopTest{@TestpublicvoidtestAop01(){AnnotationConfigApplicationContext=newAnnotationConfigApplicationContext(AopConfig.class);MathHandlermathHandler=context.getBean(Math;mathHandler.class)(1,2);context.close();}}运行AopTest类中的testAop01()方法,输出信息如下。加法运算开始,参数列表为:{}目标方法执行加法运算,加法正常返回。运行结果:{}可以看到执行了切面类中的方法,并打印了相关信息。但是不打印参数列表和运行结果。6.在切面类中打印参数列表并返回结果。需要打印参数表和运行结果怎么办?别着急,我们继续往下看。要打印出参数列表和运行结果,需要对LogAspect类中的方法进行优化,优化后的结果如下图。packageio.mykit.spring.plugins.register.aspect;importorg.aspectj.lang.JoinPoint;importorg.aspectj.lang.annotation.*;importjava.util.Arrays;/***@authorbinghe*@version1.0.0*@description用于打印日志的切面类*/@AspectpublicclassLogAspect{@Pointcut("execution(publicintio.mykit.spring.plugins.register.aop.MathHandler.*(..))")publicvoidpointCut(){}@Before("pointCut()")publicvoidlogStart(JoinPointjoinPoint){System.out.println(joinPoint.getSignature().getName()+"运行开始,参数列表为:{"+Arrays.asList(joinPoint.getArgs())+"}");}@After("pointCut()")publicvoidlogEnd(JoinPointjoinPoint){System.out.println(joinPoint.getSignature().getName()+"操作结束");}@AfterReturning(value="pointCut()",returning="result")publicvoidlogReturn(JoinPointjoinPoint,Objectresult){System.out.println(joinPoint.getSignature().getName()+"正常返回,运行结果:{"+result+"}");}@AfterThrowing(值=“pointCut()”,投掷="exception")publicvoidlogException(JoinPointjoinPoint,Exceptionexception){System.out.println(joinPoint.getSignature().getName()+"异常,异常信息:{"+exception+"}");}}这里,需要要注意的是:JoinPoint参数必须放在参数的首位此时,我们再次运行AopTest类中的testAop01()方法,输出结果信息如下。添加操作开始,参数列表为:{[1,2]}目标方法执行添加,操作结束。添加正常返回,运行结果:{3}7.目标方法抛出异常。我们在MathHandler类的add()方法中抛出一个异常,来测试异常情况,如下图。packageio.mykit.spring.plugins.register.aop;/***@authorbinghe*@version1.0.0*@description定义了一个用于测试AOP的数据处理器类*/publicclassMathHandler{publicintadd(inti,intj){System.out.println("目标方法执行");thrownewRuntimeException();//returni+j;}}此时,我们再次运行AopTest类中的testAop01()方法,输出结果信息如下。添加操作开始,参数列表为:{[1,2]}目标方法执行添加操作结束添加异常,异常信息:{java.lang.RuntimeException}可以看出信息部分中打印的正确输出。至此,我们的AOP测试环境就搭建成功了。本文转载自微信公众号“银禾科技”,可通过以下二维码关注。转载本文请联系冰川科技公众号。