概述
ReflectASM是一个很小的java类库,它仅仅有5个类,但是却提供了非常高性能的属性操作、方法调用、构造方法调用,它在底层使用了asm(https://www.ibm.com/developerworks/cn/java/j-lo-asm30/index.html)动态构建出字节码,这相比于反射,直接方法的调用性能高出很多。
可以看下官方给出的性能对比:
原理分析
以MethodAccess为例,使用方式很简单
MethodAccess access = MethodAccess.get(SomeClass.class);
access.invoke(someObject, "setName", "abc");
通过get方法得到某个类的加强类,直接调用类上的setName完成方法的调用,主要的过程便是在get方法中,它通过asm生成SomeClass的代理类,实现了MethodAccess的invoke方法,方法的内容是生成SomeClass的所有方法的调用index,这样可以通过指定方法名称的方式调用类上的方法。直接调用类上方法的速度肯定要快于反射调用了
复制类
应用中用到从一个类到另外一个类的copy使用ReflectASM性能会好很多,具体的方式如下:
其中对于耗时的get操作增加了缓存,代理类生成一次就够了
public class ReflectAsmManager {
private static final ConcurrentMap<Class, MethodAccess> localCache = Maps.newConcurrentMap();
public static MethodAccess get(Class clazz) {
if(localCache.containsKey(clazz)) {
return localCache.get(clazz);
}
MethodAccess methodAccess = MethodAccess.get(clazz);
localCache.putIfAbsent(clazz, methodAccess);
return methodAccess;
}
public static <F,T> void copyProperties(F from, T to) {
MethodAccess fromMethodAccess = get(from.getClass());
MethodAccess toMethodAccess = get(to.getClass());
Field[] fromDeclaredFields = from.getClass().getDeclaredFields();
for(Field field : fromDeclaredFields) {
String name = field.getName();
try {
Object value = fromMethodAccess.invoke(from, "get" + StringUtils.capitalize(name), null);
toMethodAccess.invoke(to, "set" + StringUtils.capitalize(name), value);
} catch (Exception e) {
// 设置异常,可能会没有对应字段,忽略
}
}
}
}