概述
利用jvm的指令集直接构造class,简单的bean class 还是有应用场景的。在此利用ASM和Javassist各造例子以备忘!
抽象类:SimpleJbean
public abstract class SimpleJbean {
public abstract byte[] createBeanClass(String className, List<FieldInfo> fields);
}
ASM实现:
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import com.FieldInfo;
import com.SimpleJbean;
/**
* SimpleJbean.java. 2011-12-28下午4:12:18 @author LionBule.
*/
public class SimpleJbeanAsm extends SimpleJbean implements Opcodes {
@Override
public byte[] createBeanClass(String className, List<FieldInfo> fields) {
ClassWriter cw = new ClassWriter(0);
cw.visit(V1_1, ACC_PUBLIC, className, null, "java/lang/Object", null);
// creates a MethodWriter for the (implicit) constructor
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
// create set&get methods
for (FieldInfo f : fields) {
addMethod(cw, mv, className, f);
}
return cw.toByteArray();
}
private void addMethod(ClassWriter cw, MethodVisitor mv, String className,
FieldInfo fieldInfo) {
String fieldName = fieldInfo.name;
String setMethodName = "set" + StringUtils.capitalize(fieldName);
String getMethodName = "get" + StringUtils.capitalize(fieldName);
String typeof = Type.getType(fieldInfo.type).getDescriptor();
String getof = getof(typeof);
String setof = setof(typeof);
int[] loadAndReturnOf = loadAndReturnOf(typeof);
//add field
cw.visitField(ACC_PRIVATE, fieldName, typeof, null, 0).visitEnd();
// getMethod
mv = cw.visitMethod(ACC_PUBLIC, getMethodName, getof, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, fieldName, typeof);
mv.visitInsn(loadAndReturnOf[1]);
mv.visitMaxs(2, 1);
mv.visitEnd();
// setMethod
mv = cw.visitMethod(ACC_PUBLIC, setMethodName, setof, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(loadAndReturnOf[0], 1);
mv.visitFieldInsn(PUTFIELD, className, fieldName, typeof);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
private String setof(String typeof) {
return "(" + typeof + ")V";
}
private String getof(String typeof) {
return "()" + typeof;
}
private int[] loadAndReturnOf(String typeof) {
if (typeof.equals("I") || typeof.equals("Z")) {
return new int[]{ILOAD,IRETURN};
} else if (typeof.equals("J")) {
return new int[]{LLOAD,LRETURN};
} else if (typeof.equals("D")) {
return new int[]{DLOAD,DRETURN};
} else if (typeof.equals("F")) {
return new int[]{FLOAD,FRETURN};
} else {
return new int[]{ALOAD,ARETURN};
}
}
}
Javassist实现:
import java.util.List;
import org.apache.commons.lang.StringUtils;
import com.FieldInfo;
import com.SimpleJbean;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
/**
* JbeanUtil.java. 2011-12-26下午4:05:02 @author LionBule.
*/
public class SimpleJbeanJs extends SimpleJbean {
private final static String SETTER_STR
= "set";
private final static String GETTER_STR
= "get";
// type/fieldName
private final static String fieldTemplate = "private %s %s;";
@Override
public byte[] createBeanClass(String className, List<FieldInfo> fields){
try{
ClassPool cpool = ClassPool.getDefault();
CtClass cc = cpool.makeClass(StringUtils.capitalize(className));
String setMethodName = null;
String getMethodName = null;
for (FieldInfo fi : fields) {
setMethodName = SETTER_STR + StringUtils.capitalize(fi.name);
getMethodName = GETTER_STR + StringUtils.capitalize(fi.name);
CtField newField = CtField.make(String.format(fieldTemplate, fi.type.getName(), fi.name), cc);
cc.addField(newField);
CtMethod ageSetter = CtNewMethod.setter(setMethodName, newField);
cc.addMethod(ageSetter);
CtMethod ageGetter = CtNewMethod.getter(getMethodName, newField);
cc.addMethod(ageGetter);
}
return cc.toBytecode();
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
单元测试:
import static org.junit.Assert.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.junit.Before;
import org.junit.Test;
import com.asm.util.SimpleJbeanAsm;
import com.javassist.util.SimpleJbeanJs;
/**
* SimpleJbeanTest.java. 2011-12-30下午9:00:09 @author LionBule.
*/
public class SimpleJbeanTest extends ClassLoader {
private String
className;
private List<FieldInfo> fields;
@Before
public void setUp() throws Exception {
className = "User";
FieldInfo testString = new TestFieldInfo(String.class, "name", "lionbule");
FieldInfo testInt = new TestFieldInfo(int.class, "age", 27);
FieldInfo testLong = new TestFieldInfo(long.class, "count", 9999999999L);
FieldInfo testFloat = new TestFieldInfo(float.class, "score", 89.312F);
FieldInfo testDouble = new TestFieldInfo(double.class, "number", 89.3121313D);
FieldInfo testBoolean = new TestFieldInfo(Boolean.class, "isStudent", false);
fields = new ArrayList<FieldInfo>();
fields.add(testString);
fields.add(testInt);
fields.add(testLong);
fields.add(testFloat);
fields.add(testDouble);
fields.add(testBoolean);
}
@Test
public void testSimpleJbeanJs() {
try {
SimpleJbean simpleJbean = new SimpleJbeanJs();
doAction(simpleJbean);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
@Test
public void testSimpleJbeanAsm() {
try {
SimpleJbean simpleJbean = new SimpleJbeanAsm();
doAction(simpleJbean);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
private void doAction(SimpleJbean simpleJbean) throws Exception {
byte[] classBytes = simpleJbean.createBeanClass(className, fields);
Class<?> userClass = this.defineClass(className, classBytes, 0, classBytes.length);
//invoker
Object user = userClass.newInstance();
TestFieldInfo tempField = null;
for (FieldInfo t : fields) {
tempField = (TestFieldInfo) t;
String setMethodName = "set" + StringUtils.capitalize(tempField.name);
String getMethodName = "get" + StringUtils.capitalize(tempField.name);
Method setMethod = userClass.getMethod(setMethodName, new Class[] { tempField.type });
setMethod.invoke(user, new Object[] { tempField.value });
Method getMethod = userClass.getMethod(getMethodName, new Class[] {});
System.out.println(getMethod.toGenericString());
Object result = getMethod.invoke(user, new Object[] {});
assertEquals(tempField.value, result);
}
}
}
ASM和Javassist的区别和侧重点,google下有很多资料,不再详述。
看了上面列子也会有大概的感触!
源码地址:
http://lionbule-java-open.googlecode.com/svn/trunk/lionbule-compile
reference:
1. http://asm.ow2.org/doc/developer-guide.html
2. http://download.forge.objectweb.org/asm/asm4-guide.pdf
最后
以上就是自由冷风为你收集整理的利用ASM和Javassist动态生成Class 类(set和get)的全部内容,希望文章能够帮你解决利用ASM和Javassist动态生成Class 类(set和get)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复