package jef.accelerator.bean; import static jef.accelerator.asm.ASMUtils.doUnwrap; import static jef.accelerator.asm.ASMUtils.doWrap; import static jef.accelerator.asm.ASMUtils.getDesc; import static jef.accelerator.asm.ASMUtils.getMethodDesc; import static jef.accelerator.asm.ASMUtils.getPrimitiveType; import static jef.accelerator.asm.ASMUtils.getType; import static jef.accelerator.asm.ASMUtils.iconst; import java.lang.reflect.Method; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.Set; import jef.accelerator.asm.ClassWriter; import jef.accelerator.asm.FieldVisitor; import jef.accelerator.asm.Label; import jef.accelerator.asm.MethodVisitor; import jef.accelerator.asm.Type; import jef.tools.reflect.BeanUtils; final class ASMSwitcherGenerator extends ClassGenerator { public ASMSwitcherGenerator(Class<?> beanClass, String accessorName, FieldInfo[] fields,ClassLoader cl) { super(beanClass,accessorName,fields,cl); } public byte[] generate() { ClassWriter cw = new ClassWriter(0); cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER + ACC_FINAL, accessorName,null, "jef/accelerator/bean/SwitchBeanAccessor", new String[] {}); // field { FieldVisitor fw = cw.visitField(ACC_PRIVATE, "fields", getDesc(java.util.Set.class), null,null); fw.visitEnd(); MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "getPropertyNames", "()Ljava/util/Collection;", null,null); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, accessorType, "fields", getDesc(java.util.Set.class)); mw.visitInsn(ARETURN); mw.visitMaxs(1, 1); mw.visitEnd(); } // //构造器 { MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,null); mw.visitVarInsn(ALOAD, 0); mw.visitMethodInsn(INVOKESPECIAL, "jef/accelerator/bean/SwitchBeanAccessor", "<init>", "()V"); mw.visitTypeInsn(NEW, getType(HashSet.class)); mw.visitInsn(DUP); mw.visitMethodInsn(INVOKESPECIAL, getType(HashSet.class), "<init>", "()V"); mw.visitVarInsn(ASTORE, 1); mw.visitVarInsn(ALOAD, 0); mw.visitVarInsn(ALOAD, 1); mw.visitFieldInsn(PUTFIELD, accessorType, "fields", getDesc(java.util.Set.class)); for (FieldInfo info : fields) { mw.visitVarInsn(ALOAD, 1); mw.visitLdcInsn(info.getName()); mw.visitMethodInsn(INVOKEINTERFACE, getType(Set.class), "add", "(Ljava/lang/Object;)Z"); mw.visitInsn(POP); } mw.visitInsn(RETURN); mw.visitMaxs(2, 2); mw.visitEnd(); } { MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "getProperty", getMethodDesc(Object.class, Object.class, String.class), null,null); mw.visitVarInsn(ALOAD, 1); mw.visitTypeInsn(CHECKCAST, beanType); mw.visitVarInsn(ASTORE, 3); mw.visitVarInsn(ALOAD, 2); mw.visitMethodInsn(INVOKEVIRTUAL, getType(String.class), "hashCode", "()I"); SwitchHelper sw = new SwitchHelper(); mw.visitLookupSwitchInsn(sw.defaultLabel, sw.hashs, sw.labels); for (int i = 0; i < sw.size(); i++) { mw.visitLabel(sw.labels[i]); mw.visitVarInsn(ALOAD, 3); Method getter=sw.f[i].getGetter(); Class<?> fieldType = getter.getReturnType(); generateInvokeMethod(mw,getter); if (fieldType.isPrimitive()) { doWrap(mw, fieldType); } mw.visitInsn(ARETURN); } { mw.visitLabel(sw.defaultLabel); mw.visitTypeInsn(NEW, getType(NoSuchElementException.class)); mw.visitInsn(DUP); mw.visitTypeInsn(NEW, getType(StringBuilder.class)); mw.visitInsn(DUP); mw.visitVarInsn(ALOAD, 2); mw.visitMethodInsn(INVOKESPECIAL, getType(StringBuilder.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitLdcInsn(" is not exist in " + beanClass.getName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "append", getMethodDesc(StringBuilder.class, String.class)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "toString", getMethodDesc(String.class)); mw.visitMethodInsn(INVOKESPECIAL, getType(NoSuchElementException.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitInsn(ATHROW); } mw.visitMaxs(5, 4); mw.visitEnd(); } { // setProperty MethodVisitor mw = cw.visitMethod(ACC_PUBLIC , "setProperty", getMethodDesc(Boolean.TYPE, Object.class, String.class, Object.class), null,null); mw.visitVarInsn(ALOAD, 1); mw.visitTypeInsn(CHECKCAST, beanType); mw.visitVarInsn(ASTORE, 4); mw.visitVarInsn(ALOAD, 2); mw.visitMethodInsn(INVOKEVIRTUAL, getType(String.class), "hashCode", "()I"); SwitchHelper sw = new SwitchHelper(); mw.visitLookupSwitchInsn(sw.defaultLabel, sw.hashs, sw.labels); Label success = new Label(); Label ifnull=new Label(); for (int i = 0; i < sw.size(); i++) { mw.visitLabel(sw.labels[i]); mw.visitVarInsn(ALOAD, 4); mw.visitVarInsn(ALOAD, 3); Method setter=sw.f[i].getSetter(); Class<?> type = setter.getParameterTypes()[0]; if (type.isPrimitive()) { mw.visitInsn(DUP); mw.visitJumpInsn(IFNULL, ifnull); Class<?> wrapped = BeanUtils.toWrapperClass(type); mw.visitTypeInsn(CHECKCAST, getType(wrapped)); doUnwrap(mw, type, wrapped); } else { mw.visitTypeInsn(CHECKCAST, getType(type)); } generateInvokeMethod(mw, setter); if(setter.getReturnType()!=void.class){ mw.visitInsn(POP); //丢掉 } if (i < sw.size() - 1) { mw.visitJumpInsn(GOTO, success);// 最后一个分支不使用goto语句,确保success标签就在之后。 } } {//必须在第一位 mw.visitLabel(success); mw.visitInsn(ICONST_1); mw.visitInsn(IRETURN); } { mw.visitLabel(sw.defaultLabel); mw.visitInsn(ICONST_0); mw.visitInsn(IRETURN); } { mw.visitLabel(ifnull); mw.visitInsn(POP); //S1 mw.visitInsn(POP); //S0 mw.visitInsn(ICONST_1); mw.visitInsn(IRETURN); } mw.visitMaxs(3, 5); mw.visitEnd(); } { MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "getPropertyType", getMethodDesc(Class.class, String.class), null,null); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKEVIRTUAL, getType(String.class), "hashCode", "()I"); SwitchHelper sw = new SwitchHelper(); mw.visitLookupSwitchInsn(sw.defaultLabel, sw.hashs, sw.labels); for (int i = 0; i < sw.size(); i++) { mw.visitLabel(sw.labels[i]); if( fields[i].isPrimitive()){ getPrimitiveType(mw,fields[i].getRawType()); }else{ mw.visitLdcInsn(Type.getType(fields[i].getRawType())); } mw.visitInsn(ARETURN); } { mw.visitLabel(sw.defaultLabel); mw.visitTypeInsn(NEW, getType(NoSuchElementException.class)); mw.visitInsn(DUP); mw.visitTypeInsn(NEW, getType(StringBuilder.class)); mw.visitInsn(DUP); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKESPECIAL, getType(StringBuilder.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitLdcInsn(" is not exist in " + beanClass.getName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "append", getMethodDesc(StringBuilder.class, String.class)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "toString", getMethodDesc(String.class)); mw.visitMethodInsn(INVOKESPECIAL, getType(NoSuchElementException.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitInsn(ATHROW); } mw.visitMaxs(5, 2); mw.visitEnd(); } { MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "getGenericType", getMethodDesc(java.lang.reflect.Type.class, String.class), null,null); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKEVIRTUAL, getType(String.class), "hashCode", "()I"); SwitchHelper sw = new SwitchHelper(); mw.visitLookupSwitchInsn(sw.defaultLabel, sw.hashs, sw.labels); for (int i = 0; i < sw.size(); i++) { mw.visitLabel(sw.labels[i]); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, accessorType, "genericType", "[Ljava/lang/reflect/Type;"); iconst(mw, i); mw.visitInsn(AALOAD); mw.visitInsn(ARETURN); } { mw.visitLabel(sw.defaultLabel); mw.visitTypeInsn(NEW, getType(NoSuchElementException.class)); mw.visitInsn(DUP); mw.visitTypeInsn(NEW, getType(StringBuilder.class)); mw.visitInsn(DUP); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKESPECIAL, getType(StringBuilder.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitLdcInsn(" is not exist in " + beanClass.getName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "append", getMethodDesc(StringBuilder.class, String.class)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "toString", getMethodDesc(String.class)); mw.visitMethodInsn(INVOKESPECIAL, getType(NoSuchElementException.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitInsn(ATHROW); } mw.visitMaxs(5, 2); mw.visitEnd(); } { MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "getAnnotationOnField", getMethodDesc(java.util.Map.class, String.class), null,null); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKEVIRTUAL, getType(String.class), "hashCode", "()I"); SwitchHelper sw = new SwitchHelper(); mw.visitLookupSwitchInsn(sw.defaultLabel, sw.hashs, sw.labels); for (int i = 0; i < sw.size(); i++) { mw.visitLabel(sw.labels[i]); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, accessorType, "fieldAnnoMaps", "[Ljava/util/Map;"); iconst(mw, i); mw.visitInsn(AALOAD); mw.visitInsn(ARETURN); } { mw.visitLabel(sw.defaultLabel); mw.visitTypeInsn(NEW, getType(NoSuchElementException.class)); mw.visitInsn(DUP); mw.visitTypeInsn(NEW, getType(StringBuilder.class)); mw.visitInsn(DUP); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKESPECIAL, getType(StringBuilder.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitLdcInsn(" is not exist in " + beanClass.getName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "append", getMethodDesc(StringBuilder.class, String.class)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "toString", getMethodDesc(String.class)); mw.visitMethodInsn(INVOKESPECIAL, getType(NoSuchElementException.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitInsn(ATHROW); } mw.visitMaxs(5, 2); mw.visitEnd(); } { MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "getAnnotationOnGetter", getMethodDesc(java.util.Map.class, String.class), null,null); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKEVIRTUAL, getType(String.class), "hashCode", "()I"); SwitchHelper sw = new SwitchHelper(); mw.visitLookupSwitchInsn(sw.defaultLabel, sw.hashs, sw.labels); for (int i = 0; i < sw.size(); i++) { mw.visitLabel(sw.labels[i]); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, accessorType, "getterAnnoMaps", "[Ljava/util/Map;"); iconst(mw, i); mw.visitInsn(AALOAD); mw.visitInsn(ARETURN); } { mw.visitLabel(sw.defaultLabel); mw.visitTypeInsn(NEW, getType(NoSuchElementException.class)); mw.visitInsn(DUP); mw.visitTypeInsn(NEW, getType(StringBuilder.class)); mw.visitInsn(DUP); mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKESPECIAL, getType(StringBuilder.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitLdcInsn(" is not exist in " + beanClass.getName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "append", getMethodDesc(StringBuilder.class, String.class)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "toString", getMethodDesc(String.class)); mw.visitMethodInsn(INVOKESPECIAL, getType(NoSuchElementException.class), "<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitInsn(ATHROW); } mw.visitMaxs(5, 2); mw.visitEnd(); } { MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "getAnnotationOnSetter", getMethodDesc(java.util.Map.class, String.class), null,null); mw.visitVarInsn(ALOAD, 1); //S1 mw.visitMethodInsn(INVOKEVIRTUAL,getType(String.class), "hashCode", "()I"); //S1 SwitchHelper sw = new SwitchHelper(); mw.visitLookupSwitchInsn(sw.defaultLabel, sw.hashs, sw.labels); for (int i = 0; i < sw.size(); i++) { mw.visitLabel(sw.labels[i]); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, accessorType, "setterAnnoMaps", "[Ljava/util/Map;"); iconst(mw, i); mw.visitInsn(AALOAD); mw.visitInsn(ARETURN); } { mw.visitLabel(sw.defaultLabel); mw.visitTypeInsn(NEW, getType(NoSuchElementException.class));//S1 mw.visitInsn(DUP); //S2 mw.visitTypeInsn(NEW, getType(StringBuilder.class)); //S3 mw.visitInsn(DUP); //S4 mw.visitVarInsn(ALOAD, 1); //S5 mw.visitMethodInsn(INVOKESPECIAL, getType(StringBuilder.class), "<init>",getMethodDesc(Void.TYPE, String.class)); mw.visitLdcInsn(" is not exist in " + beanClass.getName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class),"append", getMethodDesc(StringBuilder.class, String.class)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(StringBuilder.class), "toString", getMethodDesc(String.class)); mw.visitMethodInsn(INVOKESPECIAL, getType(NoSuchElementException.class),"<init>", getMethodDesc(Void.TYPE, String.class)); mw.visitInsn(ATHROW); } mw.visitMaxs(5, 2); mw.visitEnd(); } super.generatePublicMethods(cw); cw.visitEnd(); return cw.toByteArray(); } private class SwitchHelper { private Label[] labels; private int[] hashs; private FieldInfo[] f; private Label defaultLabel; int size() { return f.length; } SwitchHelper() { defaultLabel = new Label(); f = fields; labels = new Label[fields.length]; hashs=new int[fields.length]; for (int i = 0; i < fields.length; i++) { hashs[i] = fields[i].getName().hashCode(); labels[i] = new Label(); } } } }