龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > JAVA开发 >

Java 1.5中面向方面(AOP)编程[组图](4)

时间:2009-12-23 15:42来源:未知 作者:admin 点击:
分享到:
下面是表现一个普通方法调用的字节码,它被StatusManager更新环绕着: 0: ldc #2; //字符串消息 2: invokestatic #3; //方法StatusManager.push:(LString;)V 5: invokestatic #4;

  下面是表现一个普通方法调用的字节码,它被StatusManager更新环绕着:

  0: ldc #2; //字符串消息
  2: invokestatic #3; //方法StatusManager.push:(LString;)V
  5: invokestatic #4; //方法 doSomething:()V
  8: invokestatic #5; //方法 StatusManager.pop:()V
  11: return

  下面是相同的方法调用,但是位于try-finally代码块中,因此,如果它产生了异常会调用StatusManager.pop():

  0: ldc #2; //字符串消息
  2: invokestatic #3; //方法 StatusManager.push:(LString;)V
  5: invokestatic #4; //方法 doSomething:()V
  8: invokestatic #5; //方法 StatusManager.pop:()V
  11: goto 20
  14: astore_0
  15: invokestatic #5; //方法 StatusManager.pop:()V
  18: aload_0
  19: athrow
  20: return

  Exception table:
  from to target type
  5 8 14 any
  14 15 14 any


  你可以发现,为了实现一个try-finally,我必须复制一些指令,并添加了几个跳转和异常表记录。幸运的是,BCEL的InstructionList类使这种工作相当简单。

  在运行时重构字节码

  现在我拥有了一个基于注解修改类的接口和该接口的具体实现了,下一步是编写调用它的实际框架组件。实际上我将编写少量的框架组件,先从运行时重构所有类的框架组件开始。由于这种操作会在build过程中发生,我决定为它定义一个Ant事务。build.xml文件中的重构目标的声明应该如下:


  <instrument class="com.pkg.OurInstrumentor">
  <fileset dir="$(classes.dir)">
  <include name="**/*.class"/>
  </fileset>
  </instrument>


  为了实现这种事务,我必须定义一个实现org.apache.tools.ant.Task接口的类。我们的事务的属性和子元素(sub-elements)都是通过set和add方法调用传递进来的。我们调用执行(execute)方法来实现事务所要执行的工作--在示例中,就是重构<fileset>中指定的类文件。


  public class InstrumentTask extends Task {
  ...
  public void setClass (String className) { ... }
  public void addFileSet (FileSet fileSet) { ... }

  public void execute () throws BuildException {
  Instrumentor inst = getInstrumentor();

  try {
   DirectoryScanner ds =fileSet.getDirectoryScanner(project);
   // Java 1.5 的"for" 语法
   for (String file : ds.getIncludedFiles()) {
    instrumentFile(inst, file);
   }
  } catch (Exception ex) {
   throw new BuildException(ex);
  }
  }
  ...
  }

精彩图集

赞助商链接