返回列表 发帖

无需Eclipse使用AspectJ

下载和安装AspectJ
下载和安装AspectJ请按如下步骤进行:
(1)登录http://www.eclipse.org/aspectj/downloads.php#stable_release站点,下载AspectJ的最新稳定版本,本书下载AspectJ1.6.1版。
(2)下载完成后得到一个aspectj-1.6.1.jar文件,该文件名中1.6.1表示AspectJ的版本号。
(3)启动命令行窗口,进入aspectj-1.6.1.jar文件所在路径,输入如下命令:
java -jar aspectj-1.6.1.jar
(4)运行上面命令将开始安装AspectJ。
(5)单击对话框中的“Next”按钮,系统将出现如下图所示对话框,该对话框用于选择JDK安装路径:

(6)如果上图8所示对话框的JDK安装路径正确,直接单击“Next”按钮即可;否则读者应该通过右边的“Browse”按钮来选择JDK安装路径,正确选择了JDK安装路径后单击“Next”按钮,系统将再次出现一个话框,该对话框用于选择AspectJ的安装路径。

提示:正如图8.7所看到的,笔者没有将AspectJ安装在C盘,甚至没有安装在D盘,这是因为AspectJ是“纯绿色”软件,安装AspectJ的实质是解压缩了一个压缩包,并不需要向Windows注册表、系统路径里添加任何“垃圾”信息,因此保留AspectJ安装后的文件夹,即使以后重装Windows系统,而AspectJ不会受到任何影响。
(7)选择了合适的安装路径后,单击图8.7所示对话框的“Install”按钮,程序开始安装AspectJ,安装结束后出现一个对话框,单击该对话框中的“Next”按钮,将弹出安装完成的对话框。
(8)安装了AspectJ之后,系统还应该为将E:\Java\AOP\aspectj1.6\bin路径添加到PATH环境变量中,还应该将E:\Java\AOP\aspectj1.6\lib\aspectjrt.jar添加到CLASSPATH环境变量中。
提示:AspectJ提供了编译、运行AspectJ的一些工具命令,这些工具命令放在AspectJ的bin路径下,而lib\路径下aspectjrt.jar则是AspectJ的运行时环境,所以我们需要添加分别添加这两个环境变量——就像安装了JDK也需要添加环境变量一样。关于如何添加环境变量请参阅笔者所注的《疯狂Java讲义》一书。
AspectJ使用入门

成功安装了AspectJ之后,将会在E:\Java\AOP\aspectj1.6路径下(AspectJ的安装路径)看到如下文件结构:
 bin:该路径下存放了aj、aj5、ajc、ajdoc、ajbrowser等命令,其中ajc命令最常用,它的作用类似于javac,用于对普通Java类进行编译时增强。
 docs:该路径下存放了AspectJ的使用说明、参考手册、API文档等文档。
 lib:该路径下的四个JAR文件是AspectJ的核心类库。
 相关授权文件。
一些文档、AspectJ入门书籍,一谈到使用AspectJ,就认为必须使用Eclipse工具,似乎离开了该工具就无法使用AspectJ了。
注意:虽然AspectJ是Eclipse基金组织的开源项目,而且提供了Eclipse的AJDT插件(AspectJ Development Tools)来开发AspectJ应用,但AspectJ绝对无需依赖于Eclipse工具。
实际上AspectJ的用法非常简单,就像我们使用JDK编译、运行Java程序一样。下面通过一个简单的程序来示范AspectJ的用法。
首先编写一个简单的Java类,这个Java类用于模拟一个业务组件:
  1. public class Hello 
  2. {
  3.  //定义一个简单方法,模拟应用中的业务逻辑方法
  4.  public void sayHello()
  5.  {
  6.          System.out.println("Hello AspectJ!");
  7.  }
  8.  //主方法,程序的入口
  9.  public static void main(String[] args) 
  10.  {
  11.          Hello h = new Hello();
  12.          h.sayHello();
  13.  }
  14. }
复制代码
上面Hello类模拟了一个业务逻辑组件,编译、运行该Java程序,这个结果是没有任何悬念的,程序将在控制台打印“Hello AspectJ”字符串。
假设现在客户需要在执行sayHello()方法之前启动事务,当该方法执行结束结束事务,在传统编程模式下,我们必须手动修改sayHello()方法——如果改为使用AspectJ,则可以无需修改上面的sayHello()方法。下面我们定义一个特殊的Java类:
  1. public aspect TxAspect 
  2. {
  3.  //指定执行Hello.sayHello()方法时执行下面代码块
  4.  void around():call(void Hello.sayHello())
  5.  {
  6.          System.out.println("开始事务...");
  7.          proceed();
  8.          System.out.println("事务结束...");
  9.  }
  10. }
复制代码
可能读者已经发现了,上面类文件中不是使用class、interface、enum在定义Java类,而是使用了aspect——难道Java语言又新增了关键字?没有!上面的TxApect根本不是一个Java类,所以aspect也不是Java支持的关键字,它只是AspectJ才能识别的关键字。
上面粗体字代码也不是方法,它只是指定当程序执行Hello对象的sayHello()方法时,系统将改为执行粗体字代码的花括号代码块,其中proceed()代表调用原来的sayHello()方法。
正如前面提到了,Java无法识别TxAspect.java文件的内容,所以我们要使用ajc.exe命令来编译上面的Java程序:
ajc -d . Hello.java TxAspect.java
提示:我们可以把ajc.exe理解成javac.exe命令,都用于编译Java程序,区别是ajc.exe命令可识别AspectJ的语法;从这个意义上看,我们可以将ajc.exe当成一个增强版的javac.exe命令。
运行该Hello类依然无需任何改变,因为Hello类位于lee包下,程序使用如下命令运行Hello类:
java lee.Hello
运行该程序将看到一个令人惊喜的结果:
开始事务...
Hello AspectJ!
事务结束...
从上面运行结果来看,我们完全可以不对Hello.java类进行任何修改,同时又可以满足客户的需求:上面程序只是在控制台打印“开始事务...”、“结束事务...”来模拟了事务操作,实际上我们可用实际的事务操作代码来代替这两行简单的语句,这就可以满足客户需求了。
如果客户再次提出新需求,需要在sayHello()方法后增加记录日志的功能,那也很简单,我们再定义一个LogAspect,程序如下:
  1. public aspect LogAspect 
  2. {
  3.  //定义一个PointCut,其名为logPointcut
  4.  //该PointCut对应于指定Hello对象的sayHello方法
  5.  pointcut logPointcut()
  6.          :execution(void Hello.sayHello());
  7.  //在logPointcut之后执行下面代码块
  8.  after():logPointcut()
  9.  {
  10.          System.out.println("记录日志...");
  11.  }
  12. }
复制代码
上面程序的粗体字代码定义了一个Pointccut:logPointcut——等同于执行Hello对象的sayHello()方法,并指定在logPointcut之后执行简单的代码块,就是说在sayHello()方法之后执行指定代码块。使用如下命令来编译上面的Java程序:
ajc -d . *.java
再次运行Hello类,将看到如下运行结果:
开始事务...
Hello AspectJ!
记录日志...
事务结束...
由此可见,通过使用AspectJ提供的AOP支持,我们可以为sayHello()方法不断增加新功能。
如果读者安装过Java的反编译工具,可以反编译前面程序生成的Hello.class文件,我们将发现该Hello.class文件不是由Hello.java文件编译得到的,该Hello.class里新增了很多内容——这表明AspectJ在编译时已增强了Hello.class类的功能,因此AspectJ通常被称为编译时增强的AOP框架。
提示:与AspectJ相对的还有另外一种AOP框架,它们不需要在编译时对目标类进行增强,而是运行时生成目标类的代理类,该代理类要么与目标类实现相同的接口,要么是目标类的子类——总之,代理类都对目标类进行了增强处理,前者是JDK动态代理的处理策略,后者是CGLIB代理的处理策略。Spring AOP以创建动态代理的方式来生成代理类,底层既可使用JDK动态代理,也可采用CGLIB代理。关于创建JDK动态代理的方式可参考笔者所著的《疯狂Java讲义》18章。
实际上AspectJ允许同时为多个方法添加新功能,只要我们定义Pointcut时指定匹配更多的方法即可,例如如下片段:
pointcut xxxPointcut()
 :execution(void H*.say*());
上面程序中的xxxPointcut将可以匹配所有以H开头类中、所有以say开头的方法,但该方法返回之必须是void;如果不想匹配任意的返回值类型,则可将代码改为如下形式:
pointcut xxxPointcut()
 :execution(* H*.say*());
关于如何定义AspectJ中的Aspect、Pointcut等,读者可以参考AspectJ安装路径下的doc目录里的quick5.pdf文件。
实际上本书更喜欢使用Ant来管理AspectJ应用,此时只要使用iajc task来编译AspectJ Java程序即可,为了能正常使用iajc task,应该先使用taskdef来定义该task,本应用所使用的build.xml文件中有如下两段:
  1. <!-- 定义iajc task -->
  2. <taskdef resource=
  3.  "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
  4.  <classpath refid="classpath"/>
  5. </taskdef>
  6. <!-- 使用iajc编译包含AspecJ的Java程序 -->
  7. <iajc destdir="${dest}" debug="true"
  8.  deprecation="false" failonerror="true">
  9.  <src path="${src}"/>
  10.  <classpath refid="classpath"/>
  11. </iajc>
复制代码

——本文节选自《轻量级Java EE企业应用实战》

[ 本帖最后由 kongyeeku 于 2008-8-10 12:01 编辑 ]
clip_image002.jpg
生命没有假期!
如果生命只剩下最后一秒,你可会想到我?

好东西啊。。这个东西感觉灵活性超大。。对代码基本没有影响。。真正的热插拔啊。。

TOP

返回列表