1. 序

Aspect Oriented Programming (AOP)是近来一个比较热门的话题。 
AspectJ是AOP的Java语言的实现,获得了Java程序员的广泛关注。 
关于AspectJ和AOP的具体资料,请从下列链接中查找: 
http://www.eclipse.org/aspectj/ 
http://www.parc.com/research/csl/projects/aspectj/ 
http://aosd.net/

初次接触AspectJ的读者看到这些资料(或者语法手册),会感到AspectJ有些神秘。
他们想知道,AspectJ是如何做到这些的?AspectJ是怎样工作的?AspectJ需要特殊的运行环境吗? 
本文从讲解AspectJ的设计思路、运行原理入手,回答上述问题。

本文讲解的主要内容,按照概念的重要程度,排列如下:

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

2.Aspect Oriented Programming (AOP)

本节简单介绍AOP的概念,解释我们为什么需要AOP。 
AOP是Object Oriented Programming(OOP)的补充。
OOP能够很好地解决对象的数据和封装的问题,却不能很好的解决Aspect("方面")分离的问题。下面举例具体说明。

比如,我们有一个Bank(银行)类。Bank有两个方法,deposit(存钱)和withdraw(取钱)。 
类和方法的定义如下(Code 2.1 Bank.java):

class Bank
{
    public float deposit(AccountInfo account, float money)
    {
      // 增加account账户的钱数,返回账户里当前的钱数
    }
    public float withdraw(AccountInfo account, float money)
    {
      // 减少account账户的钱数,返回取出的钱数
    }
};

这两个方法涉及到用户的账户资金等重要信息,必须要非常小心,所以编写完上面的商业逻辑之后,项目负责人又提出了新的要求--给Bank类的每个重要方法加上安全认证特性。 
于是,我们不得不分别在上面的两个方法中加入安全认证的代码。

类和方法的定义如下(Code 2.2 Bank.java):

class Bank
{
    public float deposit(AccountInfo account, float money)
    {
      // 验证account是否为合法用户
      // 增加account账户的钱数,返回账户里当前的钱数
    }
    public float withdraw(AccountInfo account, float money)
    {
      // 验证account是否为合法用户
      // 减少account账户的钱数,返回取出的钱数
    }
};

这两个方法都需要操作数据库,为了保持数据完整性,项目负责人又提出了新的要求--给Bank类的每个操作数据库的方法加上事务控制。 
于是,我们不得不分别在上面的两个方法中加入事务控制的代码。

类和方法的定义如下(Code 2.3 Bank.java):

class Bank
{
public float deposit(AccountInfo account, float money)
{
  // 验证account是否为合法用户
  // Begin Transaction
  // 增加account账户的钱数,返回账户里当前的钱数
  // End Transaction
}
public float withdraw(AccountInfo account, float money)
{
  // 验证account是否为合法用户
  // Begin Transaction
  // 减少account账户的钱数,返回取出的钱数
  // End Transaction
}
};

我们看到,这些与商业逻辑无关的重复代码遍布在整个程序中。实际的工程项目中涉及到的类和函数,远远不止两个。如何解决这种问题? 
这个例子中提到的认证,事务等方面,就是AOP所关心的Aspect。 
AOP就是为了解决这种问题而出现的。AOP的目的就是--Separation of Aspects (or Separation of Concerns). 
下面的章节,解释AspectJ工具如何解决Separation of Aspects的问题。

3.AspectJ

这一节我们来看看AspectJ如何实现上例中的Separation of Aspects。 
使用AspectJ,我们不用对原有的代码做任何修改,就可以为代码提供不同的Aspect(方面)--比如,认证,事务等。

我们只需要提供两个不同的Aspect--认证Aspect和事务Aspect。
Code 4.1 AuthAspect.java

aspect AuthAspect
{
  pointcut bankMethods() : execution (* Bank.deposit(…)) || execution (* Bank. withdraw (…));
  Object around(): bankMethods()
  {
    // 验证account是否为合法用户
    return proceed();
  }
};

Code 4.2 TransactionAspect.java

aspect TransactionAspect
{
  pointcut bankMethods() : execution(* Bank.deposit(…)) || execution (* Bank. withdraw (…));
  Object around(): bankMethods()
  {
    // Begin Transaction
    Object result = proceed();
    // End Transaction
    return result;
  }
};

如果您暂时不能理解这段代码,没有关系,后面会讲到,这些aspect的定义,不过是定义了一些代码生成规则。 
我们用AspectJ编译器编译Bank文件和含有aspect的这个文件,出来的结果就是带有安全认证和事务处理的Bank类。编译出来的这个Bank类调用了AspectJ Runtime Lib,所以,如果你要运行这个Bank类,你需要把AspectJ Runtime Lib设置在你的classpath里面。

我们来看看,AspectJ编译器为我们做了什么事情。

首先,AspectJ从文件列表里取出所有的文件名,然后读取这些文件,进行分析。 
AspectJ发现一些文件含有aspect的定义,在这个例子里,就是AuthAspect和TransactionAspect的定义;这些aspect就是代码生成规则。 
AspectJ根据这些aspect代码生成规则,修改添加你的源代码。在这个例子里,就是修改添加Bank文件。 
AspectJ读取AuthAspect的定义,发现了一个pointcut--bankMethods();这个pointcut的定义是execution(* Bank.deposit(…)) || execution(* Bank. withdraw (…)),表示所有对Bank类的deposit和withdraw方法的执行点。 
AspectJ继续读取AuthAspect的定义,发现了一个around(),这在AspectJ中叫做Advice,我不明白为什么叫这个名字,不过没关系,我们只要知道它是干什么的就行了。Advice允许你在某个类的方法的调用之前或调用之后,加入另外的代码。Code 4.1所示代码中的around()的" // 验证account是否为合法用户"部分,就是要加入的代码。这段代码要加在哪里呢?around()后面跟了一个pointcut--bankMethods()。根据这个pointcut,AspectJ会把这段代码加入到Bank.deposit和Bank.withdraw两个方法的执行之前。达到的效果就如同Code 2.2所示。 
AspectJ读取TransactionAspect的定义,象第(4)步一样,发现了发现了一个pointcut--bankMethods()。 
AspectJ继续读取AuthAspect的定义,发现了一个around()。这次AspectJ把"Begin Transaction"和"End Transaction"两段代码加在Bank.deposit和Bank. withdraw两个方法的执行前后。达到的效果就如同Code 2.3所示。

如何验证这一点?您可以到 http://www.eclipse.org/aspectj/下载安装AspectJ,编译里面的Sample,把编译结果反编译一下,就可以看到AspetJ自动生成的代码。 
我们看到,AspectJ是一种代码自动生成工具。你编写一段通用的代码,比如认证方面的代码,事务方面的代码,然后根据AspectJ语法定义一套代码生成规则(aspect定义),AspectJ就会帮助你自动把这段通用代码分布到对应的代码里面去,简单快捷,算无遗策。 
无独有偶,一个著名的编译器生成工具--Java Compiler Compiler (JavaCC),也采用了非常相似的代码生成机制。JavaCC允许你在语法定义规则文件中,加入你自己的Java代码,用来处理读入的各种语法元素。 
AspectJ令你的代码更精简,结构更良好。AspectJ的好处,我就不多说了,网上很多精彩的文章探讨AspectJ的各种用途。

4.总结

开源项目的出现,打破了软件技术领域的众多壁垒,推动软件技术进程的日新月异。 
同时,一些新名词,新概念也层出不穷,令人眼花缭乱,无所适从。其实,很多东西都是换汤不换药,我们理解应用这些新技术的时候,要抓住本质,要破除迷信,破除任何人为的神秘感。

互联网时代的权威,不是说出来的,而是做出来的。

另外,围绕着一些有前途的新技术,总会出现大量的"快速入门手册",有些简直就是对该技术帮助文档的翻译,而且,有难度的地方没有翻译出来,大家都明白的地方翻译得非常详尽,详尽到了没有必要的地步。这种因为市场需求而产生的应景时文,大量地出现在技术文章领域。

Java AOP - Aspectj的更多相关文章

  1. Java AOP nested exception is java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice || Error creating bean with name 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#0' 两个异常解决办法

    贴出applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...

  2. Spring3系列12- Spring AOP AspectJ

    Spring3系列12- Spring AOP AspectJ 本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代 ...

  3. Spring AOP + AspectJ annotation example

    In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...

  4. Spring AOP + AspectJ Annotation Example---reference

    In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...

  5. Java AOP (1) compile time weaving 【Java 切面编程 (1) 编译期织入】

    According to wikipedia  aspect-oriented programming (AOP) is a programming paradigm that aims to inc ...

  6. Spring AOP AspectJ

    本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...

  7. Spring AOP @AspectJ 入门基础

    需要的类包: 1.一个简单的例子 Waiter接口: package com.yyq.annotation; public interface Waiter { void greetTo(String ...

  8. 关于 Spring AOP (AspectJ) 该知晓的一切

    关联文章: 关于Spring IOC (DI-依赖注入)你需要知道的一切 关于 Spring AOP (AspectJ) 你该知晓的一切 本篇是年后第一篇博文,由于博主用了不少时间在构思这篇博文,加上 ...

  9. AOP AspectJ 字节码 示例 Hugo MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

随机推荐

  1. MySQL5.7解压版详细安装教程,在最后一步需要随机密码

    这里为百度经验 http://jingyan.baidu.com/article/ff42efa93580c4c19e2202b6.html 然而在最后一步,回车不能够越过密码. 需要在解压的mysq ...

  2. 使用CATransformLayer制作3D图像和动画

    之前我们讲过可以用CALayer搭配CATransform3D来实现将View做3D旋转, 今天我们再看一个3D的新东西 CATransformLayer, 看名字就知道这个layer跟旋转有关, 那 ...

  3. SVG基础以及使用Javascript DOM操作SVG

    SVG 不依赖分辨率 支持事件处理器 最适合带有大型渲染区域的应用程序(比如谷歌地图) 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快) 不适合游戏应用 Canvas 依赖分辨率 不支持事 ...

  4. 【C#】Get the html code of a webpage

    As for the title,the console program will show you a sample which can get the webpage-code.Enjoy it: ...

  5. WPF 使用WinForm Chart控件

    第一步:  页面 首先引用命名空间 xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFor ...

  6. 数据库开启gtid时,需要注意的问题

    1.slave不能执行任何sql,包括超级用户2.read_only=on,这个必须要开启,避免业务执行sql3.保证当前slave的事务id为1 当slave同步出现问题时,手动跳过,需要考虑的问题 ...

  7. 【锋利的Jquery】读书笔记十一

    项目进度太赶,天天公司加班12小时,没时间看书充电.2016年再更新一篇吧.现在凌晨2点36分. 2017加油哦 jquery合适的选择器 $("#id") 无疑是最佳提高性能的方 ...

  8. Extjs控件属性

    Ext.form.TimeField: 配置项:            maxValue:列表中允许的最大时间            maxText:当时间大于最大值时的错误提示信息          ...

  9. Notepad++中调试用心lua程序

    一.配置: 1.打开Notepad++: 2. 按下F5,或者打开Run->Run… 3. 弹出Run的窗口 3. 这一步是最关键的,将下列语句拷贝粘贴至输入框中:cmd /k Python & ...

  10. mybatis学习笔记三(关联关系)

    学习mybatis的关联关系,主要注解在代码上,这里不做解释.配置文件一样的就不贴了 1.关联关系表创建(学生对应老师 多对一) 学生老师表 2.表对应的实体类 package com.home.en ...