java ASM创建一个简单的注解类
准备工作
请看 java ASM创建一个简单的类 的准备工作
查看一个注解编译后的样子
我已正常的思维创建了一个SimpleAnnotation类, 这个类只有一个value方法, 其次有两个默认值
@interface SimpleAnnotation {
String[] value() default {"默认值1", "默认值2"};
}
我们再次用IDEA的View -> Show ByteCode功能查看Color字节码
这是查看后的样子
abstract @interface runstatic/asmexample/CreateSimpleAnnotationExample$SimpleAnnotation implements java/lang/annotation/Annotation {
// access flags 0x401
public abstract value()[Ljava/lang/String;
default={"\u9ed8\u8ba4\u503c1", "\u9ed8\u8ba4\u503c2"}
}
使用ASM进行写入
public static void main(String[] args) throws Exception {
// 这里面给0即刻 ClassWriter.COMPUTE_MAXS和ClassWriter.COMPUTE_FRAMES暂时不需要用
ClassWriter cw = new ClassWriter(0);
// 构造
cw.visit(
V1_8, // 生成的源码版本
ACC_PUBLIC | ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE, // 生成的作用域
"runstatic/asmexample/SimpleAnnotation", // 生成的Class名称
null, // 泛型信息会传入此参数 现在不考虑泛型
"", // 因为是Annotation, 相当于是一个接口, 所有没有父类
new String[]{
Type.getDescriptor(Annotation.class) // 这个是实现的接口, 所有注解都默认实现的这个类
}
);
// 注解的参数方法
final MethodVisitor value = cw.visitMethod(
ACC_PUBLIC | ACC_ABSTRACT,
"value",
Type.getMethodDescriptor(Type.getType(String[].class)),
null,
new String[0]
);
value.visitCode();
// 访问默认值
final AnnotationVisitor aDefault = value.visitAnnotationDefault().visitArray(null);
aDefault.visit(null, "默认值1");
aDefault.visit(null, "默认值2");
// 这行必须加👇, 要不然默认值不会写入
aDefault.visitEnd();
value.visitEnd();
cw.visitEnd();
// 由于注解不能通过代码方式查看就通过文件方式打印
final byte[] bytes = cw.toByteArray();
File file = new File("./build/asmTarget/runstatic/asmexample");
if (!file.isDirectory() && file.mkdirs()) {
System.out.println("目录创建成功");
}
// 输出
final OutputStream outputStream = new FileOutputStream("./build/asmTarget/runstatic/asmexample/SimpleAnnotation.class");
outputStream.write(bytes);
}
代码运行后我们再通过IDEA的工具进行查看
结果跟我们之前用java写的一样