WEB开发网
开发学院软件开发Java Classworking 工具箱: 注释(Annotation)与 ASM 阅读

Classworking 工具箱: 注释(Annotation)与 ASM

 2010-03-18 00:00:00 来源:WEB开发网   
核心提示: J2SE 5.0 的 instrumentation 特性远远不止是我在此所展示的,它包括访问加载到 JVM 中的所有类,Classworking 工具箱: 注释(Annotation)与 ASM(7),甚至重定义已有类(如果 JVM 支持的话)的能力,对于本文,允许您只对感兴趣的 visito

J2SE 5.0 的 instrumentation 特性远远不止是我在此所展示的,它包括访问加载到 JVM 中的所有类,甚至重定义已有类(如果 JVM 支持的话)的能力。对于本文,我将跳过其他的特性,继续来看用于处理注释和修改类的 ASM 代码。

累积元数据

ASM 2.0 使处理注释变得更容易了。正如您在 上个月的文章 中了解到的,ASM 使用 visitor 的方法来报告类数据的所有组件。J2SE 5.0 注释是使用 org.objectweb.asm.AnnotationVisitor 接口报告的。该接口定义了几个方法,其中我将只使用两个:visitAnnotation() 是处理注释时调用的方法,而 visit() 是处理注释的特定的名值对时调用的方法。我还需要实际字段信息,这是使用基本 org.objectweb.asm.ClassVisitor 接口中的 visitField() 方法报告的。

实现感兴趣的两个接口的所有方法将是冗长乏味的,但幸运的是 ASM 提供了一个方便的 org.objectweb.asm.commons.EmptyVisitor 类,作为编写自己的 visitor 的基础。EmptyVisitor 只是提供了所有不同种类的 visitor 的空的实现,允许您只对感兴趣的 visitor 方法建子类和重写。清单 5 给出了扩展 EmptyVisitor 类而得到的处理 ToString 注释的 FieldCollector 类。清单中也包含了用来保存收集的字段信息的 FieldInfo 类。

清单 5. 处理类的注释

package com.sosnoski.asm; 
import java.util.ArrayList; 
import java.util.Arrays; 
import org.objectweb.asm.AnnotationVisitor; 
import org.objectweb.asm.FieldVisitor; 
import org.objectweb.asm.Opcodes; 
import org.objectweb.asm.Type; 
import org.objectweb.asm.commons.EmptyVisitor; 
/** 
 * Visitor implementation to collect field annotation information from class. 
 */ 
public class FieldCollector extends EmptyVisitor 
{ 
  private boolean m_isIncluded; 
  private int m_fieldAccess; 
  private String m_fieldName; 
  private Type m_fieldType; 
  private int m_fieldOrder; 
  private String m_fieldText; 
  private ArrayList m_fields = new ArrayList(); 
   
  // finish field handling, once we're past it 
  private void finishField() { 
    if (m_isIncluded) { 
      m_fields.add(new FieldInfo(m_fieldName, m_fieldType, 
        m_fieldOrder, m_fieldText)); 
    } 
    m_isIncluded = false; 
  } 
   
  // return array of included field information 
  public FieldInfo[] getFields() { 
    finishField(); 
    FieldInfo[] infos = 
      (FieldInfo[])m_fields.toArray(new FieldInfo[m_fields.size()]); 
    Arrays.sort(infos); 
    return infos; 
  } 
   
  // process field found in class 
  public FieldVisitor visitField(int access, String name, String desc, 
    String sig, Object init) { 
     
    // finish processing of last field 
    finishField(); 
     
    // save information for this field 
    m_fieldAccess = access; 
    m_fieldName = name; 
    m_fieldType = Type.getReturnType(desc); 
    m_fieldOrder = Integer.MAX_VALUE; 
     
    // default text is empty if non-String object, otherwise from field name 
    if (m_fieldType.getSort() == Type.OBJECT && 
      !m_fieldType.getClassName().equals("java.lang.String")) { 
      m_fieldText = ""; 
    } else { 
      String text = name; 
      if (text.startsWith("m_") && text.length() > 2) { 
        text = Character.toLowerCase(text.charAt(2)) + 
          text.substring(3); 
      } 
      m_fieldText = text; 
    } 
    return super.visitField(access, name, desc, sig, init); 
  } 
   
  // process annotation found in class 
  public AnnotationVisitor visitAnnotation(String sig, boolean visible) { 
     
    // flag field to be included in representation 
    if (sig.equals("Lcom/sosnoski/asm/ToString;")) { 
      if ((m_fieldAccess & Opcodes.ACC_STATIC) == 0) { 
        m_isIncluded = true; 
      } else { 
        throw new IllegalStateException("ToString " + 
          "annotation is not supported for static field +" + 
          " m_fieldName"); 
      } 
    } 
    return super.visitAnnotation(sig, visible); 
  } 
   
  // process annotation name-value pair found in class 
  public void visit(String name, Object value) { 
     
    // ignore anything except the pair defined for toString() use 
    if ("order".equals(name)) { 
      m_fieldOrder = ((Integer)value).intValue(); 
    } else if ("text".equals(name)) { 
      m_fieldText = value.toString(); 
    } 
  } 
} 
package com.sosnoski.asm; 
import org.objectweb.asm.Type; 
/** 
 * Information for field value to be included in string representation. 
 */ 
public class FieldInfo implements Comparable 
{ 
  private final String m_field; 
  private final Type m_type; 
  private final int m_order; 
  private final String m_text; 
   
  public FieldInfo(String field, Type type, int order, 
    String text) { 
    m_field = field; 
    m_type = type; 
    m_order = order; 
    m_text = text; 
  } 
  public String getField() { 
    return m_field; 
  } 
  public Type getType() { 
    return m_type; 
  } 
  public int getOrder() { 
    return m_order; 
  } 
  public String getText() { 
    return m_text; 
  } 
   
  /* (non-Javadoc) 
   * @see java.lang.Comparable#compareTo(java.lang.Object) 
   */ 
  public int compareTo(Object comp) { 
    if (comp instanceof FieldInfo) { 
      return m_order - ((FieldInfo)comp).m_order; 
    } else { 
      throw new IllegalArgumentException("Wrong type for comparison"); 
    } 
  } 
} 

上一页  2 3 4 5 6 7 8 9 10  下一页

Tags:Classworking 工具箱 注释

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接