当前位置: 首页 > 后端技术 > Java

SpringAOP与AspectJ的比较与应用

时间:2023-04-02 00:11:55 Java

1介绍AOP,即面向切面的编程是一种非常普遍的技术,尤其是在JavaWeb开发中。最流行的AOP框架分别是SpringAOP和AspectJ。2SpringAOPvsAspectJSpringAOP是基于SpringIoC实现的,它解决了大部分常见的需求,但并不是一个完整的AOP解决方案。对于非Spring容器管理的对象,它没有任何作用。AspectJ旨在提供一个完整的AOP解决方案,所以会比较复杂。2.1编织方式两者的编织方式有很大区别,这也是它们的本质区别,实现代理的方式也不同。AspectJ在运行前织入,分为三类:编译时织入编译后织入加载时织入因此需要AspectJ编译器(ajc)的支持。SpringAOP是运行时编织的,主要使用了两种技术:JDK动态代理和CGLIB代理。接口使用JDKProxy,继承接口使用CGLIB。2.2Joinpoints由于编织方式的不同,两者支持的Joinpoints也不同。final、static等方法不能通过动态代理改变,所以SpringAOP不支持。但是AspectJ在运行前直接编织了实际的代码,所以功能会强大很多。JoinpointSpringAOPSupportedAspectJSupportedMethodCallNoYesMethodExecutionYesYesConstructorCallNoYesConstructorExecutionNoYesStaticinitializerexecutionNoYesObjectinitializationNoYesFieldreferenceNoYesFieldassignmentNoYesHandlerexecutionNoYesAdviceexecutionNoYes2.3性能编译织入会比较运行时织入快很多,SpringAOP是使用代理模式在运行时才创建对应的代理类,效率没有AspectJ高。3SpringBoot使用了AspectJ,因为AspectJ的功能比较强大,在项目中会用的比较多,所以这里只介绍它与SpringBoot的集成。3.1引入依赖引入如下依赖,在SpringBoot的基础上增加了Lombok和aspectj:org.aspectjaspectjweaver<版本>${aspectj.version}org.aspectjaspectjrt${aspectj.version}org.projectlombok龙目岛${lombok.version}provided3.2AOP对象为了验证AOP的功能,我们添加了一个TestController,它有一个处理Get请求的方法会同时调用私有成员方法和静态方法:@RestController@RequestMapping("/test")@Slf4jpublicclassTestController{@GetMapping("/hello")publicStringhello(){log.info("------hello()start---");测试();静态测试();log.info("------你好()结束---");返回“你好,pkslow。”;}privatevoidtest(){log.info("-------test()开始---");日志信息(“测试”);log.info("------测试()结束---");}privatestaticvoidstaticTest(){log.info("------staticTest()开始---");log.info("staticTest");log.info("-------staticTest()结束---");}}3.3配置Aspect配置切面如下:@Aspect@Component@Slf4j//@EnableAspectJAutoProxypublicclassControllerAspect{@Pointcut("execution(*com.pkslow.springboot.controller..*.*(..))")privatevoidtestControllerPointcut(){}@Before("testControllerPointcut()")publicvoiddoBefore(JoinPointjoinPoint){log.info("-------pkslowaopdoBeforestart------");字符串方法=joinPoint.getSignature().getName();StringdeclaringTypeName=joinPoint.getSignature().getDeclaringTypeName();log.info("方法:{}.{}",declaringTypeName,方法);log.info("------pkslowaopdoBeforeend------");}@Around("testControllerPointcut()")publicObjectdoAround(ProceedingJoinPointjoinPoint)throwsThrowable{log.info("------pkslowaopdoAroundstart------");长启动=System.nanoTime();对象obj=joinPoint.proceed();长端=System.nanoTime();log.info("执行时间:"+(end-start)+"ns");log.info("------pkslowaopdoAroundend------");返回对象;@Pointcut定义了哪些类和方法将被捕获和代理,这里是控制器下的所有方法,@Before和@Around定义了一些处理逻辑。@Before是打印方法名,@Around是做计时。注意:没有必要配置@EnableAspectJAutoProxy。3.4maven插件因为需要在编译时编织代码,所以需要maven插件的支持:https://github.com/mojohaus/a...配置pom.xml文件即可。然后执行命令打包:mvncleanpackage此时会显示一些编织信息,大致如下:[INFO]Joinpoint'method-execution(java.lang.Stringcom.pkslow.springboot.controller.TestController.hello())'在类型'com.pkslow.springboot.controller.TestController'(TestController.java:14)中,由来自'com.pkslow.springboot.aop.ControllerAspect'(ControllerAspect.class(fromControllerAspect.java))[INFO]的周围建议建议加入点'method-execution(java.lang.Stringcom.pkslow.springboot.controller.TestController.hello())'在类型'com.pkslow.springboot.controller.TestController'(TestController.java:14)之前建议来自'com.pkslow.springboot.aop.ControllerAspect'的建议(ControllerAspect.class(来自ControllerAspect.java))[INFO]加入点'method-execution(voidcom.pkslow.springboot.controller.TestController.test())'输入“com.pkslow.springboot.controller.TestController”(TestController.java:22),由“com.pkslow.springboot.aop.ControllerAspect”(ControllerAspect.c)的周围建议建议lass(fromControllerAspect.java))[INFO]在类型'com.pkslow.springboot.controller.TestController'(TestController.java:22)由'com.pkslow.springboot.aop.ControllerAspect'(ControllerAspect.class(fromControllerAspect.java))[INFO]加入点'method-execution(voidcom.pkslow.springboot.controller.TestController.staticTest())'inType'com.pkslow.springboot.controller.TestController'(TestController.java:28)由'com.pkslow.springboot.aop.ControllerAspect'(ControllerAspect.class(fromControllerAspect).java))[INFO]在类型'com.pkslow.springboot.controller.TestController'(TestController.java:28)中加入点'method-execution(voidcom.pkslow.springboot.controller.TestController.staticTest())'由'com.pkslow.springboot.aop.ControllerAspect'(ControllerAspect.class(来自ControllerAspect.java))如果看到以上信息,说明代码已经织入成功。详细可以查看生成的class文件,可以看到很多代码不是我们自己写的,而是weaving生成的。3.5执行和测试编译成功后,我们执行代码。如果是通过IDEA执行的,运行前不需要构建,因为已经通过maven构建了包。可能无法通过IDEA的内置编译器构建进行编织。或者选择ajc作为编译器。具体可以参考:IDEA启动Springboot但是AOP失败。访问如下:GEThttp://localhost:8080/test/hello日志如下,成功实现AOP功能:3.6SomeerrorsencounteredErrorsencountered:ajcSyntaxerror,annotationsareOnlyavailableifsourcelevelis1.5以上需要配置插件:${java.version}${java.version}${java.version}也可以遇到无法识别Lombok的错误。下面的配置可以解决这个问题:org.codehaus.mojoaspectj-maven-plugin1.14.0${java.version}${java.version}${java.version}nonetruetrue${project.build.directory}/classescompile4AOP总结场景应用那么多,还是需要掌握代码,请看GitHub:https://github.com/LarryDpk/p...