使用ASM生成JavaBean

最近学习ASM,非常感谢哈库纳大佬的指点,推荐几篇大佬写的ASM相关博客

深入字节码 -- 使用 ASM 实现 AOP

深入字节码 -- 玩转 ASM-Bytecode

深入字节码 -- ASM 关键接口 ClassVisitor

深入字节码 -- ASM 关键接口 MethodVisitor

同时强烈推荐大佬的框架:Hasor

下面直接上代码,初学者,有不对的地方请大佬们指正!

创建java类:

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", null);
cw.visitSource(className + ".java", null);

生成<init>函数:

/**
 * 生成构造函数
 */
private void generatedInit(ClassWriter cw){
	// 构造函数
	MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
	mv.visitCode();
	Label initLabel = new Label();
	mv.visitLabel(initLabel);
	mv.visitVarInsn(ALOAD, 0);
	mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
	mv.visitInsn(RETURN);
	mv.visitMaxs(1, 1);
	mv.visitEnd();
}

为javaBean添加字段:

// 添加字段,这里添加的是public String类型的字段
cw.visitField(ACC_PUBLIC, fieldName, "Ljava/lang/String;", null, null);

写入get函数:

/**
 * 生成get方法
 */
private void generatedGet(ClassWriter cw, String name, String className){
	// 生成get函数,不接收参数,有返回值
	MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "get" + firstLetterToUpperCase(name), "()Ljava/lang/String;", null, null);
	mv.visitCode();
	Label label = new Label();
	mv.visitLabel(label);
	mv.visitVarInsn(ALOAD, 0);
	mv.visitFieldInsn(GETFIELD, className, name, "Ljava/lang/String;");
	mv.visitInsn(ARETURN);
	mv.visitMaxs(2, 2);
	mv.visitEnd();
}

写入set函数:

/**
 * 生成set方法
 */
private void generatedSet(ClassWriter cw, String name, String className){
	// 生成set函数
	MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "set" + firstLetterToUpperCase(name), "(Ljava/lang/String;)V", null, null);
	mv.visitCode();
	Label mainLabel = new Label();
	mv.visitLabel(mainLabel);
	mv.visitVarInsn(ALOAD, 0);
	mv.visitVarInsn(ALOAD, 1);
	mv.visitFieldInsn(PUTFIELD, className, name, "Ljava/lang/String;");
	mv.visitInsn(RETURN);
	mv.visitMaxs(2, 2);
	mv.visitEnd();
}

首字母转换大写:

private String firstLetterToUpperCase(String name){
	char[] cs = name.toCharArray();
	cs[0] -= (cs[0] > 96 && cs[0] < 123) ? 32 : 0;
	return String.valueOf(cs);
}

将生成的ClassWriter字节数组加载为Class:

ClassLoader.defineClass(className, data, 0, data.length);

使用javap -c,查看生成的指令文件:

public class User {
  public java.lang.String name;

  public java.lang.String nickName;

  public java.lang.String userName;

  public java.lang.String getName();
    Code:
       0: aload_0
       1: getfield      #11                 // Field name:Ljava/lang/String;
       4: areturn

  public void setName(java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #11                 // Field name:Ljava/lang/String;
       5: return

  public java.lang.String getNickName();
    Code:
       0: aload_0
       1: getfield      #17                 // Field nickName:Ljava/lang/String;
       4: areturn

  public void setNickName(java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #17                 // Field nickName:Ljava/lang/String;
       5: return

  public java.lang.String getUserName();
    Code:
       0: aload_0
       1: getfield      #22                 // Field userName:Ljava/lang/String;
       4: areturn

  public void setUserName(java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #22                 // Field userName:Ljava/lang/String;
       5: return

  public User();
    Code:
       0: aload_0
       1: invokespecial #27                 // Method java/lang/Object."<init>":()V
       4: return
}

测试运行:

public static void main(String[] args) {
	try {
		List<String> fields = new ArrayList<>();
		fields.add("name");
		fields.add("nickName");
		fields.add("userName");
		GeneratedBean generatedBean = new GeneratedBean();
		generatedBean.generatedBean(fields, "User");
		generatedBean.setMethod("nickName", "hello java");
		Object invoke = generatedBean.getMethod("nickName");
		System.out.println(invoke.toString());
	} catch (Exception e) {
		e.printStackTrace();
	}
}

运行后输出结果:

hello java

完整代码:

GeneratedBean.java

LoadClassUtil.java

猜你喜欢

转载自my.oschina.net/u/3269106/blog/920009
今日推荐