工具软件   办公软件   操作系统   网络安全   设计在线   程序开发   教程宝典   软件下载   软件论坛
您的位置:软件 > 开发者网络 > 开发工具 > Java > 正文
体验Java 1.5中面向方面(AOP)编程
[文章信息]
作者:陶刚编译
时间:2004-12-24
出处:天极网
责任编辑:方舟
[文章导读]
在本文中我将考虑使用嵌入GUI应用程序中的状态条组件的情形
advertisement
热点推荐
· 禁止QQ登录的方法
· 给你的XML文件做个数字签名
· ImageReady制作“焰火”小动画
· Java加密和数字签名编程快速入门
· 在VB6中用命令行为模式控制GUI动作
[正文]

上一页  1 2 3 4  下一页

  在类载入时重构字节码

  更好的方法可能是延迟字节码重构操作,直到字节码被载入的时候才进行重构。使用这种方法的时候,重构的字节码不用保存起来。我们的应用程序启动时刻的性能可能会受到影响,但是你却可以基于自己的系统属性或运行时配置数据来控制进行什么操作。

  Java 1.5之前,我们使用定制的类载入程序可能实现这种类文件维护操作。但是Java 1.5中新增加的java.lang.instrument程序包提供了少数附加的工具。特别地,它定义了ClassFileTransformer的概念,在标准的载入过程中我们可以使用它来重构一个类。

  为了在适当的时候(在载入任何类之前)注册ClassFileTransformer,我需要定义一个premain方法。Java在载入主类(main class)之前将调用这个方法,并且它传递进来对Instrumentation对象的引用。我还必须给命令行增加-javaagent参数选项,告诉Java我们的premain方法的信息。这个参数选项把我们的agent class(代理类,它包含了premain方法)的全名和任意字符串作为参数。在例子中我们把Instrumentor类的全名作为参数(它必须在同一行之中):

-javaagent:boxpeeking.instrument.InstrumentorAdaptor=
boxpeeking.status.instrument.StatusInstrumentor

  现在我已经安排了一个回调(callback),它在载入任何含有注解的类之前都会发生,并且我拥有Instrumentation对象的引用,可以注册我们的ClassFileTransformer了:

public static void premain (String className,
Instrumentation i)
throws ClassNotFoundException,
InstantiationException,
IllegalAccessException
{
 Class instClass = Class.forName(className);
 Instrumentor inst = (Instrumentor)instClass.newInstance();
 i.addTransformer(new InstrumentorAdaptor(inst));
}

  我们在此处注册的适配器将充当上面给出的Instrumentor接口和Java的ClassFileTransformer接口之间的桥梁。

public class InstrumentorAdaptor
implements ClassFileTransformer
{
 public byte[] transform (ClassLoader cl,String className,Class classBeingRedefined,
ProtectionDomain protectionDomain,byte[] classfileBuffer)
 {
  try {
   ClassParser cp =new ClassParser(new ByteArrayInputStream(classfileBuffer),className + ".java");
   JavaClass jc = cp.parse();

   ClassGen cg = new ClassGen(jc);

   for (Annotation an : getAnnotations(jc.getAttributes())) {
    instrumentor.instrumentClass(cg, an);
   }

   for (org.apache.bcel.classfile.Method m : cg.getMethods()) {
    for (Annotation an : getAnnotations(m.getAttributes())) {
     ConstantPoolGen cpg =cg.getConstantPool();
     MethodGen mg =new MethodGen(m, className, cpg);
     instrumentor.instrumentMethod(cg, mg, an);
     mg.setMaxStack();
     mg.setMaxLocals();
     cg.replaceMethod(m, mg.getMethod());
    }
   }
   JavaClass jcNew = cg.getJavaClass();
   return jcNew.getBytes();
  } catch (Exception ex) {
   throw new RuntimeException("instrumenting " + className, ex);
  }
 }
 ...
}

  这种在启动时重构字节码的方法位于在示例的/code/03_startup目录中。

  异常的处理

  文章前面提到,我希望编写附加的代码使用不同目的的@Status注解。我们来考虑一下一些额外的需求:我们的应用程序必须捕捉所有的未处理异常并把它们显示给用户。但是,我们不是提供Java堆栈跟踪,而是显示拥有@Status注解的方法,而且还不应该显示任何代码(类或方法的名称或行号等等)。

  例如,考虑下面的堆栈跟踪信息:

java.lang.RuntimeException: Could not load data for symbol IBM
at boxpeeking.code.YourCode.loadData(Unknown Source)
at boxpeeking.code.YourCode.go(Unknown Source)
at boxpeeking.yourcode.ui.Main+2.run(Unknown Source)
at java.lang.Thread.run(Thread.java:566)
Caused by: java.lang.RuntimeException: Timed out
at boxpeeking.code.YourCode.connectToDB(Unknown Source)
... 更多信息

  这将导致图1中所示的GUI弹出框,上面的例子假设你的YourCode.loadData()、YourCode.go()和YourCode.connectToDB()都含有@Status注解。请注意,异常的次序是相反的,因此用户最先得到的是最详细的信息。

           
           图3.显示在错误对话框中的堆栈跟踪信息

  为了实现这些功能,我必须对已有的代码进行稍微的修改。首先,为了确保在运行时@Status注解是可以看到的,我就必须再次更新@Retention,把它设置为@Retention(RetentionPolicy.RUNTIME)。请记住,@Retention控制着JVM什么时候抛弃注解信息。这样的设置意味着注解不仅可以被编译器插入字节码中,还能够使用新的Method.getAnnotation(Class)方法通过反射来进行访问。

  现在我需要安排接收代码中没有明确处理的任何异常的通知了。在Java 1.4中,处理任何特定线程上未处理异常的最好方法是使用ThreadGroup子类并给该类型的ThreadGroup添加自己的新线程。但是Java 1.5提供了额外的功能。我可以定义UncaughtExceptionHandler接口的一个实例,并为任何特定的线程(或所有线程)注册它。

  请注意,在例子中为特定异常注册可能更好,但是在Java 1.5.0beta1(#4986764)中有一个bug,它使这样操作无法进行。但是为所有线程设置一个处理程序是可以工作的,因此我就这样操作了。

  现在我们拥有了一种截取未处理异常的方法了,并且这些异常必须被报告给用户。在GUI应用程序中,典型情况下这样的操作是通过弹出一个包含整个堆栈跟踪信息或简单消息的模式对话框来实现的。在例子中,我希望在产生异常的时候显示一个消息,但是我希望提供堆栈的@Status描述而不是类和方法的名称。为了实现这个目的,我简单地在Thread的StackTraceElement数组中查询,找到与每个框架相关的java.lang.reflect.Method对象,并查询它的堆栈注解列表。不幸的是,它只提供了方法的名称,没有提供方法的特征量(signature),因此这种技术不支持名称相同的(但@Status注解不同的)重载方法。

  实现这种方法的示例代码可以在peekinginside-pt2.tar.gz文件的/code/04_exceptions目录中找到。


上一页  1 2 3 4  下一页

天极社区邀请您:写博客日记  上传相片   论坛聊天  订阅电子杂志  推荐网摘   免费图铃工具
笔名:   请您注意:

 遵守国家有关法律、法规,尊重网上道德,承担一切因您的行为而直接或间接引起的法律责任。

 天极网拥有管理笔名和留言的一切权利。
评论:
 
发表评论推荐给朋友我想参加相关培训打印我对此感兴趣订阅电子杂志
相关内容焦点新闻
  • 关于EJB的持久化对象技术分析
  • 2004开发技术年度综述之Java世界
  • Java中实现基于Aspectwerkz的AOP开发
  • 在JBoss中配置多个数据库和数据源
  • Eclipse 3.0 简介和插件开发示例
  • 民营家电商排队造手机 设备商全面杀入
  • 英特尔澄清杨旭任职传闻 官方没宣布此消息
  • 国资委河北密制联通拆分方案
  • 垃圾邮件害人害企害国 清除垃圾邮件不手软
  • 中兴携手阿尔卡特 全球逐鹿CDMA
  • 用友总裁王文京:誓将ERP变成“大众消费”
  • 香港消费者委员会:数码相机最贵未必最好
  • 外电称中兴正评估西门子手机业务 或能并购
  • Advertisement