Cglib中对jdk反射机制做了封装和调整,使用起来更加简单,同时性能也有所提升.如下为代码样例,基于cglib-2.1.3和asm-1.5.3:
1. 创建对象实例:
//通过cglib创建实例
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//创建fastClass实例,底层将根据TestObject.class字节码信息创建一个新的class:
//com.test.TestObject$$FastClassByCGLIB$$8bdfd246
//此FastClassByCGLIB类被加载后,将会被缓存起来
//缓存为一个二级map,key依次为classLoader/原始的类全名(比如com.test.TestObject)
FastClass fastClass = FastClass.create(classLoader,TestObject.class);
//-----------default constructor----------
FastConstructor defaultConstructor = fastClass.getConstructor(new Class[]{});
TestObject o1 = (TestObject)defaultConstructor.newInstance();
System.out.println(o1.testMethod());
//直接通过newInstance也可以创建对象,底层实现一样,找到默认的FastConstructor
TestObject o2 = (TestObject)fastClass.newInstance();
System.out.println(o2.testMethod());
//------------paramter constuctor----------
FastConstructor paramsConstructor = fastClass.getConstructor(new Class[]{String.class});
TestObject o3 = (TestObject)paramsConstructor.newInstance(new Object[]{"newInstance"});//传递参数
System.out.println(o3.testMethod());
//通过newInstance方式
TestObject o4 = (TestObject)fastClass.newInstance(new Class[]{String.class},new Object[]{"newInstance"});
System.out.println(o4.testMethod());
2. 方法调用:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
TestObject testObject = new TestObject("testMethod");
FastClass fastClass = FastClass.create(classLoader,TestObject.class);
//getMethod方法每次都会新建一个FastMethod对象,底层仍然继续jdk-reflect
//和JDK-reflect相比此处性能并没有太多的提升.
//
FastMethod testMethod = fastClass.getMethod("testMethod", new Class[]{});//获得testMethod方法,无参数
//testMethod.getJavaMethod();//获取java api中Method引用
String result = (String)testMethod.invoke(testObject, null);
System.out.println("invoke result:" + result);
//static method
FastMethod staticMethod = fastClass.getMethod("testStaticMethod", new Class[]{});
staticMethod.invoke(null, null);
3. MethodDelegate样例:
/**
* 简单代理(适配)工具,
* 如果你的某个对象的"某个"方法,可以被某个接口所"delegate",那么你可以使用此方式.
* 需要注意,"delegate"接口,只能被代理一个方法(即接口只能有一个方法,且签名和被代理者一致)
*
* 非常有用的方式,不过因为cglib内部缓存的机制,任何一个对象的同一个方法的delegate,事实上是同一个.
*/
public static void methodDelegate(){
TestObject testObject = new TestObject("methodDelegate");
//接口TestInterface与TestObject中,"testMethod"的签名和返回值类型必须一致.
TestInterface delegate = (TestInterface)MethodDelegate.create(testObject, "testMethod", TestInterface.class);
delegate.testMethod();
System.out.println(delegate.toString());
//静态方法
TestStaticInterface staticDelegate = (TestStaticInterface)MethodDelegate.createStatic(TestObject.class, "testStaticMethod", TestStaticInterface.class);
staticDelegate.testStaticMethod();
}
static interface TestInterface{
public String testMethod();
}
static interface TestStaticInterface{
public String testStaticMethod();
}
FastClass.create(Class),每次都创建一个新的FastClass实例,并且这个方法是有很大性能开销的,如果有必要,可以讲fastClass的实例缓存起来;对于FastClass的创建过程,底层将根据TestObject.class字节码信息创建一个新的class,例如:com.test.TestObject$$FastClassByCGLIB$$8bdfd246;不过cglib对于一个类只会创建一次,然后在本地将class引用缓存起来,缓存为一个二级map,key依次为classLoader/原始的类全名(比如com.test.TestObject).
fastMethod.getMethod(..)方法,并没有特别神奇的地方,直接调用了class.getMethod(...),然后输出一个新的Fastmethod实例,此处和class.getMethod形成差不多.不过每次都会new FastMethod().
fastMethod.invoke()的性能大概是jdk自带的Method.invoke()的1.5倍左右,只是没有像Method那样进行太多的权限检测..
尽管jdk的reflect中,对class的各种信息提供了cache,但是似乎这个cache的提升非常微弱.有个事情让我非常不解:
Class clazz = TestObject.class;
String testMethod = "testMethod";
Class[] ts = new Class[]{};
Method method = clazz.getMethod(testMethod, null);
Method method2 = clazz.getMethod(testMethod, null);
System.out.println(method == method2);//false here,why?
同一个类,使用getMethod()返回的Method的实例竟然是不同的???那reflect中还人模狗样的使用了cache,这究竟是怎么个意思?