http://www.ibm.com/developerworks/cn/java/l-aspectJ/index.html中介绍了What is AspectJ 。

  1. AspectJ是一个代码生成工具(Code Generator)。
  2. AspectJ语法就是用来定义代码生成规则的语法。您如果使用过Java Compiler Compiler (JavaCC),您会发现,两者的代码生成规则的理念惊人相似。
  3. AspectJ有自己的语法编译工具,编译的结果是Java Class文件,运行的时候,classpath需要包含AspectJ的一个jar文件(Runtime lib)。
  4. ....

看了上面几点,我就想看看它怎么把代码生成了。现在做一个试验。

一个类(包括main函数):Speaker.Java

[java] view plaincopy
  1. package test.aspectj;
  2. public class Speaker
  3. {
  4. public void speak()
  5. {
  6. System.out.println("[Speaker] bla bla ");
  7. }
  8. public static void main(String[] args)
  9. {
  10. Speaker speaker = new Speaker();
  11. speaker.speak();
  12. }
  13. }

一个aspect:AspectObserver.java

[java] view plaincopy
  1. package test.aspectj;
  2. public aspect AspectObserver
  3. {
  4. pointcut speakerSpeak():
  5. call(void *Speaker.speak());
  6. before() : speakerSpeak() {
  7. System.out.println("[AspectObserver] speaker is about to speak!");
  8. }
  9. after() returning() : speakerSpeak() {
  10. System.out.println("[AspectObserver] speaker has completed his speech!");
  11. }
  12. }

以上都是源码部分哦。

运行结果:

[java] view plaincopy
  1. [AspectObserver] speaker is about to speak!
  2. [Speaker] bla bla
  3. [AspectObserver] speaker has completed his speech!

说明程序是正常运作的哦。

好了,下面,做三个操作:

1、将以上的编译成的class文件打包成apectjtest.jar文件。

说明:可以使用ajdt的eclipse插件带的导出功能,Export -->  JAR file with ApectJ support

2、新建一个AspectJ工程,将apectjtest.jar加入类路径,使用jad来反编译Speaker.class和AspectObserver.class

得到反编译后的源码:

Speaker.class

[java] view plaincopy
  1. /*jadclipse*/// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
  2. // Jad home page: http://www.kpdus.com/jad.html
  3. // Decompiler options: packimports(3) radix(10) lradix(10)
  4. // Source File Name:   Speaker.java
  5. package test.aspectj;
  6. import java.io.PrintStream;
  7. // Referenced classes of package test.aspectj:
  8. //            AspectObserver
  9. public class Speaker
  10. {
  11. public Speaker()
  12. {
  13. }
  14. public void speak()
  15. {
  16. System.out.println("[Speaker] bla bla ");
  17. }
  18. public static void main(String args[])
  19. {
  20. Speaker speaker = new Speaker();
  21. AspectObserver.aspectOf().ajc$before$test_aspectj_AspectObserver$1$b2b6354();
  22. speaker.speak();
  23. AspectObserver.aspectOf().ajc$afterReturning$test_aspectj_AspectObserver$2$b2b6354();
  24. }
  25. }

AspectObserver.class

[java] view plaincopy
  1. /*jadclipse*/// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
  2. // Jad home page: http://www.kpdus.com/jad.html
  3. // Decompiler options: packimports(3) radix(10) lradix(10)
  4. // Source File Name:   AspectObserver.aj
  5. package test.aspectj;
  6. import java.io.PrintStream;
  7. import org.aspectj.lang.NoAspectBoundException;
  8. public class AspectObserver
  9. {
  10. public AspectObserver()
  11. {
  12. }
  13. void ajc$pointcut$$speakerSpeak$44()
  14. {
  15. }
  16. public void ajc$before$test_aspectj_AspectObserver$1$b2b6354()
  17. {
  18. System.out.println("[AspectObserver] speaker is about to speak!");
  19. }
  20. public void ajc$afterReturning$test_aspectj_AspectObserver$2$b2b6354()
  21. {
  22. System.out.println("[AspectObserver] speaker has completed his speech!");
  23. }
  24. public static AspectObserver aspectOf()
  25. {
  26. if(ajc$perSingletonInstance == null)
  27. throw new NoAspectBoundException("test_aspectj_AspectObserver", ajc$initFailureCause);
  28. else
  29. return ajc$perSingletonInstance;
  30. }
  31. public static boolean hasAspect()
  32. {
  33. return ajc$perSingletonInstance != null;
  34. }
  35. private static void ajc$postClinit()
  36. {
  37. ajc$perSingletonInstance = new AspectObserver();
  38. }
  39. private static Throwable ajc$initFailureCause;
  40. public static final AspectObserver ajc$perSingletonInstance;
  41. static
  42. {
  43. try
  44. {
  45. ajc$postClinit();
  46. }
  47. catch(Throwable throwable)
  48. {
  49. ajc$initFailureCause = throwable;
  50. }
  51. }
  52. }

3、运行一下Speaker.class

得到结果:

[java] view plaincopy
  1. [AspectObserver] speaker is about to speak!
  2. [Speaker] bla bla
  3. [AspectObserver] speaker has completed his speech!

结果跟源码运行是一样的哦(不一样就是你的人品问题咯!!)

分析一下,先理解AspectJ编译器为我们做了什么事情:

首先、AspectJ从文件列表里取出所有的文件名,然后读取这些文件,进行分析。 
二、AspectJ发现一些文件含有aspect的定义,在这个例子里,就是AspectObserver的定义;这些aspect就是代码生成规则。 
三、AspectJ根据这些aspect代码生成规则,修改添加你的源代码。在这个例子里,源码是修改成怎样了?比较一下反编译后的代码和源码便知。 
四、AspectJ读取AspectObserver的定义,发现了一个pointcut--speakerSpeak();这个pointcut的定义是call(void *Speaker.speak()),表示所有对Speaker类的speak方法的执行点。 
五、AspectJ继续读取AspectObserver的定义,发现了一个before(),这在AspectJ中叫做Advice。Advice允许你在某个类的方法的调用之前或调用之后,加入另外的代码。加入的代码是什么?比较一下反编译后的代码和源码吧。 AspectJ继续读取AspectObserver的定义.

好了,回头看看反编译后的Speaker.class,与源码Speaker.java差别在哪呢?主要在main函数中,方法被调用的前后

[java] view plaincopy
  1. public static void main(String args[])
  2. {
  3. Speaker speaker = new Speaker();
  4. AspectObserver.aspectOf().ajc$before$test_aspectj_AspectObserver$1$b2b6354();//多了这行
  5. speaker.speak();
  6. AspectObserver.aspectOf().ajc$afterReturning$test_aspectj_AspectObserver$2$b2b6354();//多了这行
  7. }

不同的地方就是多出了两行,虽然有$和数字,但是很容易看出,这同我们平常写的java代码差不了多少。

[java] view plaincopy
  1. AspectObserver.aspectOf().ajc$before$test_aspectj_AspectObserver$1$b2b6354();

这行代码中,看起来不就是AspectObserver类调用了静态方法aspectOf()吗,接着aspectOf()的返回对象又调用ajc$before$test_aspectj_AspectObserver$1$b2b6354()方法吗?

回来看看AspectObserver.class的反编译代码,哈哈,这就对了,aspectOf返回的是AspectObserver的一个实例,返回实例在调用实例方法ajc$before$test_aspectj_AspectObserver$1$b2b6354()。ajc$before$test_aspectj_AspectObserver$1$b2b6354()是干什么的呢?呵呵,不正是我们要的拦截方法所要做的操作吗?

[java] view plaincopy
  1. System.out.println("[AspectObserver] speaker is about to speak!");

同样,可知

[java] view plaincopy
  1. AspectObserver.aspectOf().ajc$afterReturning$test_aspectj_AspectObserver$2$b2b6354();

是怎么一回事啦。

这正是应了上面所提的两点:

  1. AspectJ是一个代码生成工具(Code Generator)。
  2. AspectJ语法就是用来定义代码生成规则的语法。

用这两点去感受apectj在程序里该如何去运用使用,就清晰多啦!

Spring AOP 底层原理_001----AspectJ与CGLIB介绍相关推荐

  1. Spring AOP底层原理

    什么是AOP AOP:Aspect Oriented Programing(面向切面编程) 采用横向抽取机制,取代传统继承体系重复性代码(性能监视.事务管理.安全检查.缓存)即代理机制 使用纯JAVA ...

  2. Spring AOP实现原理详解之Cglib代理实现

    引入 我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理. 要了解动态代理是如何工作 ...

  3. Spring AOP底层实现原理(动态代理)

    什么是AOP? AOP(面向切面编程)通过预编译的方式 和 运行期动态代理的方式来实现程序功能统一维护的一种方式,是OOP(面向对象编程)的延续.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业 ...

  4. [Spring5]AOP底层原理

    AOP底层原理 1.AOP底层使用动态代理 (1)有两种情况动态代理 第一种 有接口的情况,使用JDK动态代理 a.创建接口实现类代理对象,增强类的方法 第二种 没有接口的情况,使用CGLIB动态代理 ...

  5. AOP底层原理与注解配置详解

    注解开发AOP制作步骤: 在XML格式基础上 导入坐标(伴随spring-context坐标导入已经依赖导入完成 开启AOP注解支持 配置切面@Aspect 定义专用的切入点方法,并配置切入点@Poi ...

  6. Spring AOP技术(基于AspectJ)的XML开发

    Spring AOP技术(基于AspectJ)的XML开发 @(Spring)[aop, spring, xml, Spring, annotation, aspectJ] Spring AOP技术基 ...

  7. spring注解驱动开发-6 Spring AOP实现原理

    Spring AOP实现原理 前言 1.@EnableAspectJAutoProxy注解原理 2.AnnotationAwareAspectJAutoProxyCreator 分析 1.分析前工作, ...

  8. 关于Spring AOP,除了动态代理、CGLIB,你还知道什么?

    来源 | 草捏子 责编 | Carol 封图 | CSDN 付费下载于视觉中国 Spring 作为 Java 中最流行的框架,主要归功于其提供的 IOC 和 AOP 功能.本文将讨论 Spring A ...

  9. 【JAVA SE】第十七章 反射、注解与Spring事务底层原理

    第十七章 反射.注解与Spring事务底层原理 文章目录 第十七章 反射.注解与Spring事务底层原理 一.反射 1.简介 2.意义 3.缺点 4.应用场景 5.反射技术的使用 二.注解 1.概念 ...

最新文章

  1. Swift3.0和OC桥接方法
  2. 汇总|三维重建开源项目
  3. laravel 任务队列_laravel队列-让守护进程处理耗时任务
  4. Hanlp自然语言处理工具的使用演练
  5. Scikit_Learn介绍及演练
  6. 深度优先,广度优先,拓扑排序(实战题解)
  7. redhat升级linux内核,用rpm方式升级RHEL6.1内核
  8. BZOJ 4538: [Hnoi2016]网络
  9. RT-Thread Nano移植
  10. VB Vista窗体控件下载(coolBoySkin1.3版)
  11. 脑子瓦特?记忆力受损?试试AI调控的闭环电击颞叶疗法
  12. Ceylon 1.0.0
  13. Kaldi语料的两种切分/组织方式及其处理
  14. 在函数‘_start’中:对‘main’未定义的引用
  15. 190329每日一句
  16. 计算机的使用编码,计算机中使用的编码
  17. ZUI框架加上Flex布局构建登录后的主页
  18. 价值170万美元的Flash漏洞 360Vulcan免费提交给Adobe修复
  19. 判断入射满射c语言编码,数学上可以分三类函数包括() 答案:单射双射满射...
  20. “值得”关注公司:我们应该向优衣库学习什么?

热门文章

  1. Python基础----NumPy
  2. 商务部部长助理黄海:中国服务外包产业发展势头良好
  3. IIS 部署WCF时遇到这么个错:
  4. 12个必备的JavaScript装逼技巧
  5. Form Builder的三种查询方法构建
  6. session相关知识的收集于整理
  7. SQL server 2005 如何批量修改架构名(包括表名和存储过程名) .
  8. Tomcat修改源码,重新编译
  9. 关于游戏网络设计的问题
  10. ubuntu安装jdk