Spring AOP与AspectJ的对比及应用(aspect aop和spring aop)

  本篇文章为你整理了Spring AOP与AspectJ的对比及应用(aspect aop和spring aop)的详细内容,包含有springaop和aspectj aspect aop和spring aop springaop与aspectjaop区别 springaop和aspect Spring AOP与AspectJ的对比及应用,希望能帮助你了解 Spring AOP与AspectJ的对比及应用。

  AOP,即面向切面编程是很常用的技术,特别是在Java Web开发中。而最流行的AOP框架分别是Spring AOP和AspectJ。

  2 Spring AOP vs AspectJ

  Spring AOP是基于Spring IoC实现的,它解决大部分常见的需求,但它并不是一个完整的AOP解决方案。对于非Spring容器管理的对象,它更没有办法了。而AspectJ旨在提供完整的AOP方案,因此也会更复杂。

  2.1 织入方式

  两者织入方式有极大的不同,这也是它们的本质区别,它们实现代理的方式不同。

  AspectJ是在运行前织入的,分为三类:

  编译时织入

  编译后织入

  加载时织入

  因此需要AspectJ编译器(ajc)的支持。

  而Spring AOP是运行时织入的,主要使用了两种技术:JDK动态代理和CGLIB代理。对于接口使用JDK Proxy,而继承的使用CGLIB。

  2.2 Joinpoints

  因为织入方式的区别,两者所支持的Joinpoint也是不同的。像final的方法和静态方法,无法通过动态代理来改变,所以Spring AOP无法支持。但AspectJ是直接在运行前织入实际的代码,所以功能会强大很多。

  
2.3 性能

  编译织入会比较运行时织入快很多,Spring AOP是使用代理模式在运行时才创建对应的代理类,效率没有AspectJ高。

  3 Spring Boot使用AspectJ

  因为AspectJ比较强大,在项目中应用会更多,所以这里只介绍它与Spring Boot的集成。

  3.1 引入依赖

  引入以下依赖,在Spring Boot基础上加了Lombok和aspectj:

  

 dependencies 

 

   dependency

   groupId org.springframework.boot /groupId

   artifactId spring-boot-starter-web /artifactId

   /dependency

   dependency

   groupId org.aspectj /groupId

   artifactId aspectjweaver /artifactId

   version ${aspectj.version} /version

   /dependency

   dependency

   groupId org.aspectj /groupId

   artifactId aspectjrt /artifactId

   version ${aspectj.version} /version

   /dependency

   dependency

   groupId org.projectlombok /groupId

   artifactId lombok /artifactId

   version ${lombok.version} /version

   scope provided /scope

   /dependency

   /dependencies

  

 

  3.2 被AOP的对象

  为了验证AOP的功能,我们添加一个TestController,它有一个处理Get请求的方法,同时会调用private的成员方法和静态方法:

  

@RestController

 

  @RequestMapping("/test")

  @Slf4j

  public class TestController {

   @GetMapping("/hello")

   public String hello() {

   log.info("------hello() start---");

   test();

   staticTest();

   log.info("------hello() end---");

   return "Hello, pkslow.";

   private void test() {

   log.info("------test() start---");

   log.info("test");

   log.info("------test() end---");

   private static void staticTest() {

   log.info("------staticTest() start---");

   log.info("staticTest");

   log.info("------staticTest() end---");

  

 

  3.3 配置Aspect

  配置切面如下:

  

@Aspect

 

  @Component

  @Slf4j

  //@EnableAspectJAutoProxy

  public class ControllerAspect {

   @Pointcut("execution(* com.pkslow.springboot.controller..*.*(..))")

   private void testControllerPointcut() {

   @Before("testControllerPointcut()")

   public void doBefore(JoinPoint joinPoint){

   log.info("------pkslow aop doBefore start------");

   String method = joinPoint.getSignature().getName();

   String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();

   log.info("Method: {}.{}" ,declaringTypeName, method);

   log.info("------pkslow aop doBefore end------");

   @Around("testControllerPointcut()")

   public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {

   log.info("------pkslow aop doAround start------");

   long start = System.nanoTime();

   Object obj = joinPoint.proceed();

   long end = System.nanoTime();

   log.info("Execution Time: " + (end - start) + " ns");

   log.info("------pkslow aop doAround end------");

   return obj;

  

 

  @Pointcut定义哪些类和方法会被捕抓来代理,这里配置的是controller下的所有方法。

  而@Before和@Around则定义了一些处理逻辑。@Before是打印了方法名,而@Around是做了一个计时。

  注意:是不需要配置@EnableAspectJAutoProxy的。

  3.4 maven插件

  因为是需要编译时织入代码,所以需要maven插件的支持:https://github.com/mojohaus/aspectj-maven-plugin

  配置好pom.xml文件即可。

  然后执行命令打包:

  

mvn clean package

 

  

 

  这时会显示一些织入信息,大致如下:

  

[INFO] Join point method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello()) in Type com.pkslow.springboot.controller.TestController (TestController.java:14) advised by around advice from com.pkslow.springboot.aop.ControllerAspect (ControllerAspect.class(from ControllerAspect.java))

 

  [INFO] Join point method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello()) in Type com.pkslow.springboot.controller.TestController (TestController.java:14) advised by before advice from com.pkslow.springboot.aop.ControllerAspect (ControllerAspect.class(from ControllerAspect.java))

  [INFO] Join point method-execution(void com.pkslow.springboot.controller.TestController.test()) in Type com.pkslow.springboot.controller.TestController (TestController.java:22) advised by around advice from com.pkslow.springboot.aop.ControllerAspect (ControllerAspect.class(from ControllerAspect.java))

  [INFO] Join point method-execution(void com.pkslow.springboot.controller.TestController.test()) in Type com.pkslow.springboot.controller.TestController (TestController.java:22) advised by before advice from com.pkslow.springboot.aop.ControllerAspect (ControllerAspect.class(from ControllerAspect.java))

  [INFO] Join point method-execution(void com.pkslow.springboot.controller.TestController.staticTest()) in Type com.pkslow.springboot.controller.TestController (TestController.java:28) advised by around advice from com.pkslow.springboot.aop.ControllerAspect (ControllerAspect.class(from ControllerAspect.java))

  [INFO] Join point method-execution(void com.pkslow.springboot.controller.TestController.staticTest()) in Type com.pkslow.springboot.controller.TestController (TestController.java:28) advised by before advice from com.pkslow.springboot.aop.ControllerAspect (ControllerAspect.class(from ControllerAspect.java))

  

 

  看到以上信息,说明成功织入了代码,具体可以查看生成的class文件。

  可以看到有许多代码都不是我们写的,而是织入生成。

  3.5 执行及测试

  编译成功后,我们就执行代码。如果是通过IDEA来执行,则在运行前不需要再build了,因为已经通过maven build过了包。通过IDEA自带的编译器build,可能无法织入。或者选择ajc作为编译器。具体请参考:IDEA启动Springboot但AOP失效

  访问如下:

  

GET http://localhost:8080/test/hello

 

  

 

  则日志如下,成功实现AOP功能:

  3.6 一些遇到的错误

  遇到错误:

  

ajc Syntax error, annotations are only available if source level is 1.5 or greater

 

  

 

  需要配置插件:

  

 complianceLevel ${java.version} /complianceLevel 

 

   source ${java.version} /source

   target ${java.version} /target

  

 

  可能还会遇到无法识别Lombok的错误,配置如下则解决该问题:

  

 plugin 

 

   groupId org.codehaus.mojo /groupId

   artifactId aspectj-maven-plugin /artifactId

   version 1.14.0 /version

   configuration

   complianceLevel ${java.version} /complianceLevel

   source ${java.version} /source

   target ${java.version} /target

   proc none /proc

   showWeaveInfo true /showWeaveInfo

   forceAjcCompile true /forceAjcCompile

   sources/

   weaveDirectories

   weaveDirectory ${project.build.directory}/classes /weaveDirectory

   /weaveDirectories

   /configuration

   executions

   execution

   goals

   goal compile /goal

   /goals

   /execution

   /executions

   /plugin

  

 

  AOP场景应用特别多,还是需要掌握的。

  代码请看GitHub: https://github.com/LarryDpk/pkslow-samples

  以上就是Spring AOP与AspectJ的对比及应用(aspect aop和spring aop)的详细内容,想要了解更多 Spring AOP与AspectJ的对比及应用的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: