spring @aspect(aspectj spring)

在前面AspectJ的介绍中,简单介绍了AspectJ的使用,主要以AspectJ为例。介绍完后,还剩下几个问题:
1)我们看不到spring需要aspectj之类的关键字,直接用java代码就可以了。这是怎么做到的?
2)如何在2)Spring中实现aop而不用专门的编译器(如何在运行时使用AspectJ)
3)3)Spring源代码中AjType和aspectJ有什么关系?
本文将继续尝试解决这些问题。
aspectJ的几种编织方法
编译时、编译后和加载时编织器
首先了解AspectJ的几种编织方法,即编译时、后编译和加载时,分别对应编译、后编译和加载。
汇编编织
首先,编译时编织。上一篇博客中介绍的方法是使用的编译时编织。很容易理解,aspectJ(一种常见的java源代码)和aspectJ(一种特殊的编译器)的“配置”文件生成编织。类文件,并且可以在运行时直接运行。
编译后编织
编译后编织和编译的区别在于类字节码或jar文件是编织的。在这种形式下,您可以编织已经编织过一次的切割面。同样的情况也需要特殊的编译器。
装载期编织
顾名思义,加载周期是在类被加载到虚拟机之前织入的。这样,就必须使用AspectJ代理。
知道了这些概念,我们需要知道,spring用的是哪一个?春天也不是。春天是在运行时编织的。
如何在Spring中使用AspectJ
AspectJ本身不支持运行时编织。在日常使用中,我们经常听到spring使用aspectJ来实现aop。听起来好像spring的aop完全依赖于AspectJ。
其实spring是通过动态代理(jdk的动态代理或者cglib的动态代理)来实现aop的。它只使用aspectJ的注释,而不使用它的编译时和织入器。你可以看看这篇关于这个的文章,这意味着spring并没有直接使用aspectJ来实现aop。
spring aop和aspectJ的区别
看了很多博客和源代码,我对spring aop和aspectJ的理解大概是这样的;
1)spring aop使用了AspectJ语法的一个子集,aspectJ支持的一些语法,比如方法调用,类成员set/get,它不支持。
2)2)spring AOP的底层是动态代理,所以受限于此,有些增强是做不到的,比如调用自己的方法不能带代理。
请看下面的例子:
@ component public class A { public void method 1(){ method 2();} public void method2(){ //.}}这个时候method2就不能切了。如果你想被切割,你可以用以下几种奇妙的方法:
@ component public class A { @ auto wired private A A;public void method 1(){ a . method 2();} public void method2(){ //.}}以前遇到这样的问题,特别不能理解。现在当我想到aop的底层实现时,就很容易理解了。
从前面写的jdk动态代理和cglib动态代理的实现原理我们知道,jdk动态代理是通过动态生成一个类来实现的代理,也就是说代理不会修改底层类的字节码,所以可能生成的代理方法如下
Public void method1(){ //执行一段代码a.method1() //执行一段代码}public void method2(){ //执行一段代码a.method2() //执行一段代码}回头看看a.method1()的源代码,你就明白method2()为什么没有被截了。因为a.method1()执行的方法,所以它不是代理对象。method2(),而是它自己的method2()(this.method2())。这种方法本身并没有改变。
另一方面,aspectJ,aspectJ在编译时修改方法(类本身的字节码已经改变),所以在调用自己的方法时可以很容易地增强。
3)3)spring aop的代理必须依赖bean才能被spring管理,所以如果项目不使用spring,想使用AOP,只能使用aspectJ(不过现在不使用spring的项目应该不少。)
4)aspectJ的性能会比spring好,因为是编译时织的。
5)spring可以通过@EnableLoadTimeWeaving打开加载期进行编织(这个东西我也是刚知道,没怎么研究过。有兴趣可以自己研究)
6)spring aop的许多概念与aspectJ是一致的
AspectJ注释在spring aop中的应用
了解了spring和aspectJ的关系之后,我们就可以更清楚地理解spring的aop了。
首先,虽然我在介绍AspectJ配置的时候总是介绍aspectJ文件配置,但是aspectJ本身是支持注释配置的。可以看官方文档,注释aspectJ的用法。
Spring使用了一小部分aspectJ注释(如前所述,受限于jdk的动态代理,spring只支持方法级方面)。
回头看看AjType
回头看看之前看到的源代码。AjType是什么?它是被aspectJ解析器解析后的类的描述。比如正常的方法可能是这样的。
/* *配置预通知,使用方法aspect () *上注册的切入点,同时接受切入点对象,不带此参数*/@ before(\ ‘ aspect()\ ‘)public void before(join point join point){ log . info(\ ‘ before \ ‘ join point);}在AjType中,可以获得很多aspectJ所需的其他相关信息(除了java反射可以获得的信息)。
/** *返回表示此类型声明的指定切入点的切入点对象*/public Pointcut getDeclaredPointcut(String name)抛出NoSuchPointcutException/** *返回表示指定公共切入点的切入点对象*/public Pointcut getPointcut(String name)抛出NoSuchPointcutException比如看两个方法,就可以得到入口点信息。
看看PerClauseKind。SINGLETON,其中重用了aspectJ的概念。详见本文最后一部分。
总结
本文回答了我之前学习aspectJ时遇到的一些问题,然后讨论了aspectJ在spring中的应用。最大的收获是理解了spring和aspectJ之间的关系,以及两者对aop不同实现的影响。如果以后不懂spring aop相关的概念,可以去aspectJ搜==
作者:段吉

其他教程

汽车前置喇叭是高音还是低音(汽车前门喇叭是中音还是低音)

2022-9-4 3:50:09

其他教程

发烧的人能吃鸡蛋吗(发烧的故事亲身体验)

2022-9-4 3:52:13

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索