1. 程式人生 > >使用javassist代替反射完成類屬性操作工具類

使用javassist代替反射完成類屬性操作工具類

工作當中經常遇到需要使用反射進行成員變數遍歷的工作,但是使用反射的效率在高併發的情況下會比較低,這裡使用了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();

}

相關推薦

使用javassist代替反射完成屬性操作工具

工作當中經常遇到需要使用反射進行成員變數遍歷的工作,但是使用反射的效率在高併發的情況下會比較低,這裡使用了javassit的方式生成了對應的處理類,通過其例項化物件完成遍歷工作  package com.ylink.ncpc.common.util; import jav

通過泛型和反射構建一個簡單的集合操作工具

      平時在操作集合物件的時候(比如List);我想一次新增大於一個數據的時候,往往需要通過一個集合物件呼叫兩次add方法,比如: List<Person> personList=new ArrayList<>(); Person p1=n

第一章 屬性檔案操作工具

1、程式碼實現 給出的屬性檔案:http.properties(位於類路徑下) 1 #每個路由的最大連線數 2 httpclient.max.conn.per.route = 20 3 #最大總連線數 4 httpclient.max.conn.total = 400 5 #連線超時

PreferencesUtils【SharedPreferences操作工具

ast 效果圖 void 垃圾清理 extends editor nac xtend git 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 前言 可以替代ACache用來保存用戶名、密碼。 相較於Acache,不存在使用獵豹清理大師進行垃圾清理的時候把緩存的數

C#的access操作工具

C# access 操作工具類 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.OleDb; using System.Data

日期操作工具

ret catch pre pri 必須 led mem systemd stack 相關代碼如下 public class DateUtil { /** * * @param dateStyle 日期的樣式:如yyyyMMddHH

文件操作工具FileUtils

println 條件 == buffered ade mef cto override replace package yqw.java.util;import java.io.BufferedInputStream;import java.io.BufferedOutpu

常用判空操作工具

tis esc mail pre ati bst gradle otn ali 一、項目上校驗空和空集合地方非常多,可以編寫一個工具類統一校驗 package com.moy.custom.utils; import java.util.Collection; impo

c++對properties配置文件操作工具

c++ properties code源代碼GitHub路徑:源代碼地址下載 最近要使用c++對windows api相關接口的封裝,有2個接口要求讀寫properties文件。原以為網上應該有一大堆資料的,結果拜BAI度的大恩大德,一點相關的資料都沒有。那就只能自己動手豐衣足食。再次感謝十分強大只是找不到相

C#文件夾權限操作工具

輔助類 ace ont tex bject per right adding IT using System; using System.Collections.Generic; using System.IO; using System.Linq; using

電商商品規則屬性sku 工具

數據 box .get fin val type float lin use /** * 商品模塊; * 使用:var SKU = sku.init({ id:‘sku‘, item: item, data:data }); * @config item =

JavaAes加密操作工具

ssi port castle 如果 ddp arrays array xfire instance package com.king.weixin.util;import java.io.UnsupportedEncodingException;import java.s

對JAVA資原始檔操作工具

package com.kkmall.risk.common.utils; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import jav

Redis | 嘗試封裝一個操作工具

介紹 本次主要介紹以下內容: 1、SpringMVC整合Redis 2、Spring Boot整合Redis(上) 3、Spring Boot整合Redis(中) 4、Spring Boot整合Redis(下) 5、使用redis為我們提供jar進行封裝 6、使用Spring Boot提供的

HttpClient 操作工具---

原文地址: 設定post方法的header,增加紅色字型部分的配置: HttpClient client = new HttpClient(); client.getParams().setBooleanParameter( "http.protocol.expect-contin

jedis 操作工具

包括連線池的使用及 jedis對string 、set、sortset、list、hash的所有常規操作。 package com.yufei.core.util.jedis; import java.util.List; import java.util.Map; import java.u

java 時間操作工具

時間操作工具類CalendarUtil 裡面包含方法有: 獲取當前時間getInstance 字串按照格式轉換成時間strToDate 時間格式化dateToStr 獲取當天零點getSame

jQuery-CSS屬性操作

jQuery 操作 CSS jQuery 擁有若干進行 CSS 操作的方法。我們將學習下面這些: addClass() - 向被選元素新增一個或多個類 removeClass() - 從被選元素刪除一個或多個類 toggleClass() - 對被選元素進行新增/刪除

整理的關於Java對mongodb進行的CURD操作工具及原始碼

package com.iceter.DataBase; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.bson.Document; import org.bson.conversi

php的mysql操作工具pdo和mysqli

從php7開始mysql擴充套件庫已經被全面移除,原因暫不清楚,官方推薦我們使用mysqli和pdo,這次就針對pdo和mysqli分享下我的兩個工具類 1 PDO的mysql操作工具類 這種方式已經用的越來越多了,pdo使用面向物件的方式操作資料庫,pdo是很多人都比較