CGLib 动态生成 类及实例

前两天拜读深入Java虚拟机时, 看到书里有提及可以用CGLib动态生成类及类实例的做法, 就将CGLib下载下来一试.

众所周知, Java在运行时加载Class字节码到虚拟机中运行.

如下示例代码:

		try {
			URL url = new URL("file:/d:/test/lib/");
			URLClassLoader urlCL = new URLClassLoader(new URL[] { url });
			Class c = urlCL.loadClass("TestClassA");
			TestClassA object = (TestClassA) c.newInstance();
			object.method();
		} catch (Exception e) {
			e.printStackTrace();
		}

那么当然也可以在运行时动态生成Class字节码并加载到JVM中. CGLib就是很经典的字节码动态生成工具.

本人做了简单的测试, 代码如下:


import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

abstract class BaseGen {
	protected List calledMethods = new LinkedList<>(); // property

	public int getRandomInt() { // Get a random integer
		return new Random().nextInt(10000);
	}
	
	public abstract void printClassInfo(); // abstract method to print class info
}

class DynamicGen implements MethodInterceptor {

	public static  T newInstance(Class clazz) {
		Enhancer e = new Enhancer();
		e.setSuperclass(clazz);
		e.setCallback(new DynamicGen());
		return (T) e.create(); // Generate a class object
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
		Object ret = null;

		String name = method.getName();
		if (name.equals("getRandomInt")) { // intercept the getRandomInt
			ret = methodProxy.invokeSuper(obj, params); // call the base method
			System.out.println("Print random int: " + ret);
		} else if (name.equals("printClassInfo")) { // implement the print class info method
			System.out.println("Class: " + obj.getClass());
		}
		
		BaseGen baseGen = (BaseGen) obj;
		baseGen.calledMethods.add(name); // change the property

		return ret;
	}

}

public class GenCodeTest {
	public static void main(String[] args) {
		BaseGen worker = DynamicGen.newInstance(BaseGen.class); // generate a BaseGen instance
		int random = worker.getRandomInt();
		System.out.println("You can get an int: " + random); // call the method
		worker.printClassInfo(); // print instance class info
		System.out.println("Called injected methods: " + worker.calledMethods); // print the property
	}
}




你可能感兴趣的:(Java)