侧边栏壁纸
博主头像
憨憨大头个人博客博主等级

心存希冀,目有繁星

  • 累计撰写 110 篇文章
  • 累计创建 13 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

AspectJ和SpringAOP的区别

Administrator
2024-08-09 / 0 评论 / 0 点赞 / 4 阅读 / 1891 字

为什么用AspectJ

为什么用AspectJ,我的理解是两个字”方便“。我们知道面向切面编程(Aspect Oriented Programming)有诸多好处,但是在使用AspectJ之前我们一般是怎么编写切面的呢?我想一般来说应该是三种吧:静态代理,jdk动态代理,cglib动态代理。但是我们知道,静态代理的重用性太差,一个代理不能同时代理多种类;动态代理可以做到代理的重用,但是即使这样,他们调用起来还是比较麻烦,除了写切面代码以外,我们还需要将代理类耦合进被代理类的调用阶段,在创建被代理类的时候都要先创建代理类,再用代理类去创建被代理类,这就稍微有点麻烦了。比如我们想在现有的某个项目里统一新加入一些切面,这时候就需要创建切面并且侵入原有代码,在创建对象的时候添加代理,还是挺麻烦的。
说到底,这种麻烦出现的本质原因是,代理模式并没有做到切面与业务代码的解耦。虽然将切面的逻辑独立进了代理类,但是决定是否使用切面的权利仍然在业务代码中。这才导致了上面这种麻烦。
而Spring AOP里面的代理实现方式就是spring用代理类包裹切面,把他们织入到Spring管理的bean中。也就是说代理类伪装成目标类,它会截取对目标类中方法的调用,让调用者对目标类的调用都先变成调用伪装类,伪装类中就先执行了切面,再把调用转发给真正的目标bean。
Spring的这个处理确实让动态代理简洁了很多,但是,AspectJ框架对于代理的处理更加简洁,我们无需关注切点和切面(即被代理对象),只需关注我们需要织入逻辑就ok。这也是为什么Spring引用他的原因。

实现原理

而AspectJ的实现原理其实比较简单,首先是使用切面语法,这套东西做到了将决定是否使用切面的权利还给了切面。在写切面的时候就可以决定哪些类的哪些方法会被代理,从而从逻辑上不需要侵入业务代码。其次,最重要的就是他的织入工具aspectjweaver,他的作用就是在编译期(或者类加载期)将切面代码通过某种形式插入到业务代码中,也就是我们生成的.class文件其实就是相当于我们动态代理中的代理对象了。

AspectJ其实是eclipse基金会的一个项目,官网就在eclipse官网里

  • aspectjrt.jar包主要是提供运行时的一些注解,静态方法等等东西,通常我们要使用aspectJ的时候都要使用这个包。
  • aspectjtools.jar包主要是提供赫赫有名的ajc编译器,可以在编译期将将java文件或者class文件或者aspect文件定义的切面织入到业务代码中。通常这个东西会被封装进各种IDE插件或者自动化插件中。
  • aspectjweaverjar包主要是提供了一个java agent用于在类加载期间织入切面(Load time weaving)。并且提供了对切面语法的相关处理等基础方法,供ajc使用或者供第三方开发使用。这个包一般我们不需要显式引用,除非需要使用LTW。

上面的说明其实也就指出了aspectJ的几种标准的使用方法

  1. 编译时织入,利用ajc编译器替代javac编译器,直接将源文件(java或者aspect文件)编译成class文件并将切面织入进代码。
  2. 编译后织入,利用ajc编译器向javac编译期编译后的class文件或jar文件织入切面代码。
  3. 加载时织入,不使用ajc编译器,利用aspectjweaver.jar工具,使用java agent代理在类加载期将切面织入进代码。

总结

aspectJ的实现和Spring AOP是不一样的,他是直接将代码织入到编译后的class文件中。这里,也引申出一个新的问题,那Spring AOP引用aspectJ这个框架,是不是表示Spring现在也是通过织入的方式实现AOP的呢?其实spring aop还是通过动态代理来实现aop的,虽然spring aop采用了aspectj语法来定义切面,但是在实现切面逻辑的时候还是采用CGLIB来进行动态代理的方法。

0

评论区