使用示例
package fastclass;
public class DelegateClass {
public DelegateClass() {
}
public DelegateClass(String string) {
}
public boolean eat(String fruit, int i) {
System.out.println(" eat " + i + "个" + fruit);
return true;
}
public void drink() {
System.out.println("drink water");
}
}
package fastclass;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.reflect.FastClass;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @author: claude-彭方亮
* @package: fastclass.ReflectAndFastClass
* @date: 2023/3/8 11:40
* @description: TODO
* @version: 1.0
*/
public class ReflectAndFastClass {
public static void invokeReflect() throws Exception {
Class delegateClass = DelegateClass.class;
// 反射构造类
Constructor delegateConstructor = delegateClass.getConstructor(String.class);
// 创建委托类实例
DelegateClass delegateInstance = (DelegateClass) delegateConstructor.newInstance("tyrant");
// 反射方法类
Method addMethod = delegateClass.getMethod("eat", String.class, int.class);
// 调用方法
addMethod.invoke(delegateInstance, "apple", 1);
Method updateMethod = delegateClass.getMethod("drink");
updateMethod.invoke(delegateInstance);
}
public static void invokeFastClass() throws Exception {
// 保留生成的FastClass类文件
//System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "e:\proxy");
// FastClass动态子类实例
FastClass fastClass = FastClass.create(DelegateClass.class);
// 创建委托类实例
DelegateClass fastInstance = (DelegateClass) fastClass.newInstance(
new Class[] {String.class}, new Object[]{"Jack"});
// 调用委托类方法
fastClass.invoke("eat", new Class[]{ String.class, int.class}, fastInstance,
new Object[]{ "fruit", 2});
fastClass.invoke("drink", new Class[]{}, fastInstance, new Object[]{});
}
public static void main(String[] args) throws Exception {
invokeReflect();
invokeFastClass();
}
}
原理分析
FastClass不使用反射类(Constructor或Method)来调用委托类方法,而是动态生成一个新的类(继承FastClass),向类中写入委托类实例直接调用方法的语句,用模板方式解决Java语法不支持问题,同时改善Java反射性能。 动态类为委托类方法调用语句建立索引,使用者根据方法签名(方法名+参数类型)得到索引值,再通过索引值进入相应的方法调用语句,得到调用结果。
public abstract class FastClass{
// 委托类
private Class type;
// 子类访问构造方法
protected FastClass() {}
protected FastClass(Class type) {
this.type = type;
}
// 创建动态FastClass子类
public static FastClass create(Class type) {
// Generator:子类生成器,继承AbstractClassGenerator
Generator gen = new Generator();
gen.setType(type);
gen.setClassLoader(type.getClassLoader());
return gen.create();
}
/**
* 调用委托类方法
*
* @param name 方法名
* @param parameterTypes 方法参数类型
* @param obj 委托类实例
* @param args 方法参数对象
*/
public Object invoke(String name, Class[] parameterTypes, Object obj, Object[] args) {
return invoke(getIndex(name, parameterTypes), obj, args);
}
/**
* 根据方法描述符找到方法索引
*
* @param name 方法名
* @param parameterTypes 方法参数类型
*/
public abstract int getIndex(String name, Class[] parameterTypes);
/**
* 根据方法索引调用委托类方法
*
* @param index 方法索引
* @param obj 委托类实例
* @param args 方法参数对象
*/
public abstract Object invoke(int index, Object obj, Object[] args);
/**
* 调用委托类构造方法
*
* @param parameterTypes 构造方法参数类型
* @param args 构造方法参数对象
*/
public Object newInstance(Class[] parameterTypes, Object[] args) throws {
return newInstance(getIndex(parameterTypes), args);
}
/**
* 根据构造方法描述符(参数类型)找到构造方法索引
*
* @param parameterTypes 构造方法参数类型
*/
public abstract int getIndex(Class[] parameterTypes);
/**
* 根据构造方法索引调用委托类构造方法
*
* @param index 构造方法索引
* @param args 构造方法参数对象
*/
public abstract Object newInstance(int index, Object[] args);
}
FastClass分析
public class DelegateClass$$FastClassByCGLIB$$4af5b667 extends FastClass {
/**
* 动态子类构造方法
*/
public DelegateClass$$FastClassByCGLIB$$4af5b667(Class delegateClass) {
super(delegateClass);
}
/**
* 根据方法签名得到方法索引
*
* @param name 方法名
* @param parameterTypes 方法参数类型
*/
public int getIndex(String methodName, Class[] parameterTypes) {
switch(methodName.hashCode()) {
// 委托类方法add索引:0
case 96417:
if (methodName.equals("add")) {
switch(parameterTypes.length) {
case 2:
if (parameterTypes[0].getName().equals("java.lang.String") &&
parameterTypes[1].getName().equals("int")) {
return 0;
}
}
}
break;
// 委托类方法update索引:1
case -838846263:
if (methodName.equals("update")) {
switch(parameterTypes.length) {
case 0:
return 1;
}
}
break;
// Object方法equals索引:2
case -1295482945:
if (methodName.equals("equals")) {
switch(parameterTypes.length) {
case 1:
if (parameterTypes[0].getName().equals("java.lang.Object")) {
return 2;
}
}
}
break;
// Object方法toString索引:3
case -1776922004:
if (methodName.equals("toString")) {
switch(parameterTypes.length) {
case 0: return 3;
}
}
break;
// Object方法hashCode索引:4
case 147696667:
if (methodName.equals("hashCode")) {
switch(parameterTypes.length) {
case 0:
return 4;
}
}
}
return -1;
}
/**
* 根据方法索引调用委托类方法
*
* @param methodIndex 方法索引
* @param delegateInstance 委托类实例
* @param parameterValues 方法参数对象
*/
public Object invoke(int methodIndex, Object delegateInstance, Object[] parameterValues) {
DelegateClass instance = (DelegateClass) delegateInstance;
int index = methodIndex;
try {
switch(index) {
case 0:
// 委托类实例直接调用方法语句
return new Boolean(instance.add((String)parameterValues[0],
((Number)parameterValues[1]).intValue()));
case 1:
instance.update();
return null;
case 2:
return new Boolean(instance.equals(parameterValues[0]));
case 3:
return instance.toString();
case 4:
return new Integer(instance.hashCode());
}
} catch (Throwable t) {
throw new InvocationTargetException(t);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
/**
* 根据构造方法描述符(参数类型)找到构造方法索引
*
* @param parameterTypes 构造方法参数类型
*/
public int getIndex(Class[] parameterTypes) {
switch(parameterTypes.length) {
// 无参构造方法索引:0
case 0:
return 0;
// 有参构造方法索引:1
case 1:
if (parameterTypes[0].getName().equals("java.lang.String")) {
return 1;
}
default:
return -1;
}
}
/**
* 根据构造方法索引调用委托类构造方法
*
* @param methodIndex 构造方法索引
* @param parameterValues 构造方法参数对象
*/
public Object newInstance(int methodIndex, Object[] parameterValues) {
// 创建委托类实例
DelegateClass newInstance = new DelegateClass;
DelegateClass newObject = newInstance;
int index = methodIndex;
try {
switch(index) {
// 调用构造方法(<init>)
case 0:
newObject.<init>();
return newInstance;
case 1:
newObject.<init>((String)parameterValues[0]);
return newInstance;
}
} catch (Throwable t) {
throw new InvocationTargetException(t);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 4;
}
}
效率比较
FastClass和反射运行效率比较
package fastclass;
import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;
import java.lang.reflect.Method;
/**
* 效率测试
*
* @author Stone.J 2010-9-15 上午10:07:27
*/
public class Productiveness {
private static final int DEFAULT_INT = 1;
private static final Integer DEFAULT_INTEGER = 1;
private static final String DEFAULT_STRING = "name";
private static final Object[] DEFAULT_INTS = {1};
private static final Object[] DEFAULT_INTEGERS = new Integer[]{1};
private static final Object[] DEFAULT_STRINGS = new String[]{"name"};
private static final Bean BEAN = new Bean();
private static final CachedMethod CACHED_METHOD = new CachedMethod();
private static final OptimizationCachedMethod OPTIMIZATION_CACHED_METHOD = new OptimizationCachedMethod();
private static final CglibCachedMethod CGLIB_CACHED_METHOD = new CglibCachedMethod();
private static final long LOOP = 1 * 10000 * 10000;
// 测试main
public static void main(String[] args) {
// 直接调用
test();
// 反射调用
testReflection();
// 优化后反射调用
testOptimizationReflection();
// cglib反射调用
testCglibReflection();
}
// 直接调用测试
public static void test() {
long start = System.currentTimeMillis();
for (long i = 0; i < LOOP; i++) {
BEAN.setId(DEFAULT_INT);
BEAN.setCode(DEFAULT_INTEGER);
BEAN.setName(DEFAULT_STRING);
}
long dur = System.currentTimeMillis() - start;
System.out.println("直接调用测试:" + dur);
}
// 反射调用测试
public static void testReflection() {
long start = System.currentTimeMillis();
for (long i = 0; i < LOOP; i++) {
try {
CACHED_METHOD.setId.invoke(BEAN, DEFAULT_INTS);
CACHED_METHOD.setCode.invoke(BEAN, DEFAULT_INTEGERS);
CACHED_METHOD.setName.invoke(BEAN, DEFAULT_STRINGS);
} catch (Exception e) {
e.printStackTrace();
}
}
long dur = System.currentTimeMillis() - start;
System.out.println("反射调用测试:" + dur);
}
// 优化后反射调用测试
public static void testOptimizationReflection() {
long start = System.currentTimeMillis();
for (long i = 0; i < LOOP; i++) {
try {
OPTIMIZATION_CACHED_METHOD.setId.invoke(BEAN, DEFAULT_INTS);
OPTIMIZATION_CACHED_METHOD.setCode.invoke(BEAN, DEFAULT_INTEGERS);
OPTIMIZATION_CACHED_METHOD.setName.invoke(BEAN, DEFAULT_STRINGS);
} catch (Exception e) {
e.printStackTrace();
}
}
long dur = System.currentTimeMillis() - start;
System.out.println("优化后反射调用测试:" + dur);
}
// cglib反射调用测试
public static void testCglibReflection() {
long start = System.currentTimeMillis();
for (long i = 0; i < LOOP; i++) {
try {
CGLIB_CACHED_METHOD.cglibSetId.invoke(BEAN, DEFAULT_INTS);
CGLIB_CACHED_METHOD.cglibSetCode.invoke(BEAN, DEFAULT_INTEGERS);
CGLIB_CACHED_METHOD.cglibSetName.invoke(BEAN, DEFAULT_STRINGS);
} catch (Exception e) {
e.printStackTrace();
}
}
long dur = System.currentTimeMillis() - start;
System.out.println("cglib反射调用测试:" + dur);
}
/**
* <pre>
* 测试的bean
* 简单的int Integer String类型
* </pre>
*
* @author Stone.J 2010-9-15 上午10:40:40
*/
public static class Bean {
private int id;
private Integer code;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 反射测试需要:Cached Method
*
* @author Stone.J 2010-9-15 上午10:41:04
*/
public static class CachedMethod {
public Method setId;
public Method setCode;
public Method setName;
{
try {
setId = Bean.class.getDeclaredMethod("setId", int.class);
setCode = Bean.class.getDeclaredMethod("setCode", Integer.class);
setName = Bean.class.getDeclaredMethod("setName", String.class);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 反射测试需要:优化后的Cached Method
*
* @author Stone.J 2010-9-15 上午10:41:21
*/
public static class OptimizationCachedMethod extends CachedMethod {
{
/** 所谓的优化 */
setId.setAccessible(true);
setCode.setAccessible(true);
setName.setAccessible(true);
}
}
/**
* 反射测试需要,使用cglib的fast method
*
* @author Stone.J 2010-9-15 上午10:51:53
*/
public static class CglibCachedMethod extends CachedMethod {
public FastMethod cglibSetId;
public FastMethod cglibSetCode;
public FastMethod cglibSetName;
private FastClass cglibBeanClass = FastClass.create(Bean.class);
{
cglibSetId = cglibBeanClass.getMethod(setId);
cglibSetCode = cglibBeanClass.getMethod(setCode);
cglibSetName = cglibBeanClass.getMethod(setName);
}
}
}
测试了2次结果差别并不大:
直接调用测试:93
反射调用测试:1352
优化后反射调用测试:1301
cglib反射调用测试:361
直接调用测试:92
反射调用测试:1359
优化后反射调用测试:1276
cglib反射调用测试:385
参考地址:www.manongjc.com/detail/7-yu…
参考地址:www.cnblogs.com/laoxia/p/11…
cglib通过fastclass类来避免了java反射的使用。对jdk7以前的版本来说,jdk动态代理执行效率明显要比cglib动态代理类效率差,jdk8即以后版本对jdk动态代理进行了相应的优化,这种差距就不那么明显了。