工作当中经常遇到需要使用反射进行成员变量遍历的工作,但是使用反射的效率在高并发的情况下会比较低,这里使用了javassit的方式生成了对应的处理类,通过其实例化对象完成遍历工作
package com.ylink.ncpc.common.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.text.StrBuilder;
import com.ylink.ncpc.common.pojo.CommonRspPojo;
import javassist.CannotCompileException;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
/**
* 描述:使用该工具类替代反射,运行效率提高三倍以上
*
* @author songmengqiang 2015年10月26日
*/
public class FeildUtil1 {
public static void main(String[] args) {
CommonRspPojo c = new CommonRspPojo();
long cc = 1000000;
c.setReturn_code("c");
c.setReturn_msg("m");
test(c, cc);
testTmp(c, cc);
}
private static void test(CommonRspPojo c, long cc) {
final List<String> ss = new ArrayList<>();
long currentTimeMillis0 = System.currentTimeMillis();
FeildUtil1.iterate(c, new FeildCallback() {
@Override
public String busiDesc() {
return "CommonRspPojoTest";
}
@Override
public void busi(String fieldName, Object object) {
ss.add((String) object);
}
});
System.out.println("创建处理类使用的时间(毫秒):" + (System.currentTimeMillis() - currentTimeMillis0));
long currentTimeMillis = System.currentTimeMillis();
for (int i = 0; i < cc; i++) {
FeildUtil1.iterate(c, new FeildCallback() {
@Override
public String busiDesc() {
return "CommonRspPojoTest";
}
@Override
public void busi(String fieldName, Object object) {
ss.add((String) object);
}
});
}
System.out.println(ss.size());
System.out.println("javasist使用时间(毫秒):" + (System.currentTimeMillis() - currentTimeMillis));
}
private static void testTmp(CommonRspPojo c, long cc) {
final List<String> ss1 = new ArrayList<>();
FeildUtil1.iterateTemp(c, new FeildCallback() {
@Override
public String busiDesc() {
return "CommonRspPojoTest1";
}
@Override
public void busi(String fieldName, Object object) {
ss1.add((String) object);
}
});
long currentTimeMillis = System.currentTimeMillis();
for (int i = 0; i < cc; i++) {
FeildUtil1.iterateTemp(c, new FeildCallback() {
@Override
public String busiDesc() {
return "CommonRspPojoTest";
}
@Override
public void busi(String fieldName, Object object) {
ss1.add((String) object);
}
});
}
System.out.println(ss1.size());
System.out.println("反射机制使用时间(毫秒):" + (System.currentTimeMillis() - currentTimeMillis));
}
/**
* 通过反射做业务处理,但是反射的性能消耗会比较大,不推荐使用
*
* @param object
* @param FeildUtil1Callback
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
@Deprecated
public static void iterateTemp(Object object, FeildCallback FeildUtil1Callback) {
try {
Field[] declaredFields = object.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
String fieldName = field.getName();
Object fieldObj = field.get(object);
FeildUtil1Callback.busi(fieldName, fieldObj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 描述:该遍历器用来遍历所有的成员变量,如果该成员变量有对应的get方法则会调用 callback进行处理
*
* @param o
* @param fCallback
*/
public static void iterate(Object o, FeildCallback fCallback) {
String busiDesc = fCallback.busiDesc();
FeildHandlerInterface FeildUtil1Interface = handlerMap.get(busiDesc);
if (FeildUtil1Interface == null) {
try {
FeildUtil1Interface = createHandler(o, busiDesc);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
FeildUtil1Interface.iterate(o, fCallback);
}
@SuppressWarnings("unchecked")
private static synchronized FeildHandlerInterface createHandler(Object o, String busiDesc)
throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException {
//===start 当一个线程已经创建完毕,另一个线程刚好进入到该方法时则直接返回创建的结果
FeildHandlerInterface FeildUtil1Interface = handlerMap.get(busiDesc);
if (FeildUtil1Interface != null) {
return FeildUtil1Interface;
}
//===end
// 反射获取属性名数组
Class<? extends Object> class1 = o.getClass();
int busiDescHash = busiDesc.hashCode();
Field[] fields = class1.getDeclaredFields();
Map<String, Method> methodMap = new HashMap<>();
Method[] methods = class1.getMethods();
for (Method method : methods) {
methodMap.put(method.getName(), method);
}
// 反射获取类名
String classPath = class1.getName();
String name = FeildCallback.class.getName();
// 创建类继承FeildUtil1Interface
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(FeildUtil1.class));
CtClass newClass = pool.makeClass("com.ylink.ncpc.common.util.Handler" + busiDescHash);
CtClass[] list = new CtClass[] { pool.getCtClass("com.ylink.ncpc.common.util.FeildHandlerInterface") };
newClass.setInterfaces(list);
// 创建方法实现FeildUtil1Interface.iterate(o, fCallback);
String methodString = "public void iterate(Object o," + name + " fCallback){\n" + " " + classPath + " tt=("
+ classPath + ")o;\n";
for (Field field : fields) {
if (methodMap.containsKey("get" + capitalise(field.getName()))) {
methodString += "fCallback.busi(\"" + field.getName() + "\",tt.get" + capitalise(field.getName())
+ "());\n";
}
}
methodString += "}\n";
CtMethod f = CtNewMethod.make(methodString, newClass);
newClass.addMethod(f);
Class<FeildHandlerInterface> realClass = newClass.toClass();
FeildHandlerInterface newInstance = realClass.newInstance();
handlerMap.put(busiDesc, newInstance);
return newInstance;
}
/**
* 首字母大写
*
* @param str
* @return
*/
private static String capitalise(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return str;
}
return new StrBuilder(strLen).append(Character.toTitleCase(str.charAt(0))).append(str.substring(1)).toString();
}
private static Map<String, FeildHandlerInterface> handlerMap = new ConcurrentHashMap<String, FeildHandlerInterface>();
}
interface FeildHandlerInterface {
public abstract void iterate(Object o, FeildCallback fCallback);
}
package com.ylink.ncpc.common.util;
public abstract class FeildCallback{
/**
* 描述:该方法实现具体的业务
* @param fieldName
* @param object
*/
public abstract void busi(String fieldName,Object object);
/**
* 描述必须全局唯一,如果存在一样的定义,那可能会有冲突。
* 不能返回空。。
* @return
*/
public abstract String busiDesc();
}