国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

南京網(wǎng)站開發(fā)培訓(xùn)鄭州做網(wǎng)絡(luò)優(yōu)化的公司

南京網(wǎng)站開發(fā)培訓(xùn),鄭州做網(wǎng)絡(luò)優(yōu)化的公司,html做網(wǎng)站經(jīng)驗(yàn)技巧,google 字體 wordpress功能概述 PojoUtils是一個(gè)工具類,能夠進(jìn)行深度遍歷,將簡單類型與復(fù)雜類型的對象進(jìn)行轉(zhuǎn)換,在泛化調(diào)用時(shí)用到(在泛化調(diào)用中,主要將Pojo對象與Map對象進(jìn)行相互轉(zhuǎn)換) 功能分析 核心類PojoUtils分析 主要成員…

功能概述

  • PojoUtils是一個(gè)工具類,能夠進(jìn)行深度遍歷,將簡單類型與復(fù)雜類型的對象進(jìn)行轉(zhuǎn)換,在泛化調(diào)用時(shí)用到(在泛化調(diào)用中,主要將Pojo對象與Map對象進(jìn)行相互轉(zhuǎn)換)

功能分析

核心類PojoUtils分析

主要成員變量分析

private static final ConcurrentMap<String, Method> NAME_METHODS_CACHE = new ConcurrentHashMap<String, Method>(); //方法名與Method的緩存(為了減少反射獲取Method調(diào)用),key的值用類名和參數(shù)類型拼接,如:"org.apache.dubbo.common.model.Person.setName(java.lang.String)"
private static final ConcurrentMap<Class<?>, ConcurrentMap<String, Field>> CLASS_FIELD_CACHE = new ConcurrentHashMap<Class<?>, ConcurrentMap<String, Field>>(); //字段所在類Class、字段名、字段信息Filed的緩存

主要成員方法分析

generalize將復(fù)雜對象轉(zhuǎn)換為簡單對象

private static Object generalize(Object pojo, Map<Object, Object> history) { //pojo對象的成員屬性(會遞歸轉(zhuǎn)換,pojo=》Map,直到所有屬性為dubbo定義的基本類型)if (pojo == null) {return null;}if (pojo instanceof Enum<?>) {return ((Enum<?>) pojo).name(); //枚舉類型,輸出枚舉的名稱}if (pojo.getClass().isArray() && Enum.class.isAssignableFrom(pojo.getClass().getComponentType())) { //處理Enum數(shù)組int len = Array.getLength(pojo);String[] values = new String[len];for (int i = 0; i < len; i++) { //枚舉數(shù)組會轉(zhuǎn)換為String數(shù)組,數(shù)組元素的值為枚舉名values[i] = ((Enum<?>) Array.get(pojo, i)).name();}return values;}if (ReflectUtils.isPrimitives(pojo.getClass())) { //基本類型直接返回,不做處理return pojo;}if (pojo instanceof Class) { //Class類的實(shí)例,返回類名稱return ((Class) pojo).getName();}Object o = history.get(pojo);if (o != null) {return o;}history.put(pojo, pojo);if (pojo.getClass().isArray()) { //pojo對象為數(shù)組類型int len = Array.getLength(pojo);Object[] dest = new Object[len];history.put(pojo, dest);for (int i = 0; i < len; i++) {Object obj = Array.get(pojo, i);dest[i] = generalize(obj, history);}return dest;}if (pojo instanceof Collection<?>) { //pojo對象為集合類型Collection<Object> src = (Collection<Object>) pojo;int len = src.size();Collection<Object> dest = (pojo instanceof List<?>) ? new ArrayList<Object>(len) : new HashSet<Object>(len); //區(qū)分出List或Set類型,并創(chuàng)建對應(yīng)的集合實(shí)例history.put(pojo, dest);for (Object obj : src) { //遍歷集合元素,依次將元素進(jìn)行轉(zhuǎn)換dest.add(generalize(obj, history));}return dest;}if (pojo instanceof Map<?, ?>) { //pojo對象為Map類型Map<Object, Object> src = (Map<Object, Object>) pojo;Map<Object, Object> dest = createMap(src); //根據(jù)原Map類型,創(chuàng)建對應(yīng)的Map對象history.put(pojo, dest);for (Map.Entry<Object, Object> obj : src.entrySet()) {dest.put(generalize(obj.getKey(), history), generalize(obj.getValue(), history)); //key、value都可能是pojo對象,所以都需要進(jìn)行轉(zhuǎn)換}return dest;}Map<String, Object> map = new HashMap<String, Object>();history.put(pojo, map);if (GENERIC_WITH_CLZ) {map.put("class", pojo.getClass().getName()); //設(shè)置pojo對象的Class類}for (Method method : pojo.getClass().getMethods()) {if (ReflectUtils.isBeanPropertyReadMethod(method)) { //判斷是否讀取bean的方法(即get/is方法)try {/*** 處理步驟:* 1)從方法名中獲取到屬性名* 2)調(diào)用pojo對應(yīng)的方法獲取值,并通過generalize轉(zhuǎn)換(傳入history是做臨時(shí)緩存,若能從history取到則用之)* 3)將屬性名和值設(shè)置到map中*/map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history));} catch (Exception e) {throw new RuntimeException(e.getMessage(), e);}}}// public fieldfor (Field field : pojo.getClass().getFields()) {if (ReflectUtils.isPublicInstanceField(field)) { //判斷是否是公共的實(shí)例字段try {Object fieldValue = field.get(pojo);if (history.containsKey(pojo)) {Object pojoGeneralizedValue = history.get(pojo); //已經(jīng)轉(zhuǎn)換過的字段,就不再轉(zhuǎn)換if (pojoGeneralizedValue instanceof Map&& ((Map) pojoGeneralizedValue).containsKey(field.getName())) {continue;}}if (fieldValue != null) {map.put(field.getName(), generalize(fieldValue, history));}} catch (Exception e) {throw new RuntimeException(e.getMessage(), e);}}}return map;
}
  • 代碼分析:generalize方法的作用是把復(fù)雜類型對象轉(zhuǎn)換為簡單類型的對象,如將Pojo對象轉(zhuǎn)換為Map對象,Pojo對象的成員對象若還是復(fù)雜類型,會遞歸調(diào)用進(jìn)行轉(zhuǎn)換。

realize將簡單對象轉(zhuǎn)換為復(fù)雜對象

private static Object realize0(Object pojo, Class<?> type, Type genericType, final Map<Object, Object> history) { //將簡單類型轉(zhuǎn)換為復(fù)雜類型(如:將Map對象轉(zhuǎn)換為指定類型的pojo對象,將Map的屬性值,通過set方法設(shè)置到pojo對象中,type為目標(biāo)類型)if (pojo == null) {return null;}if (type != null && type.isEnum() && pojo.getClass() == String.class) { //將String轉(zhuǎn)換為枚舉類型return Enum.valueOf((Class<Enum>) type, (String) pojo);}if (ReflectUtils.isPrimitives(pojo.getClass())&& !(type != null && type.isArray()&& type.getComponentType().isEnum()&& pojo.getClass() == String[].class)) { //將String數(shù)組轉(zhuǎn)換為枚舉數(shù)組return CompatibleTypeUtils.compatibleTypeConvert(pojo, type);}Object o = history.get(pojo); //history:當(dāng)方法在遞歸調(diào)用時(shí),會用到(用緩存使用)if (o != null) {return o;}history.put(pojo, pojo);if (pojo.getClass().isArray()) { //處理數(shù)組類型的pojoif (Collection.class.isAssignableFrom(type)) { //目標(biāo)類型是集合類型Class<?> ctype = pojo.getClass().getComponentType(); //獲取數(shù)組元素的類型int len = Array.getLength(pojo); //獲取數(shù)組對應(yīng)長度Collection dest = createCollection(type, len);history.put(pojo, dest);for (int i = 0; i < len; i++) {Object obj = Array.get(pojo, i); //返回?cái)?shù)組中指定下標(biāo)的值Object value = realize0(obj, ctype, null, history); //依次將對象轉(zhuǎn)換為目標(biāo)類型,如Map轉(zhuǎn)換為pojo類型dest.add(value);}return dest;} else {Class<?> ctype = (type != null && type.isArray() ? type.getComponentType() : pojo.getClass().getComponentType());int len = Array.getLength(pojo);Object dest = Array.newInstance(ctype, len);history.put(pojo, dest);for (int i = 0; i < len; i++) {Object obj = Array.get(pojo, i);Object value = realize0(obj, ctype, null, history);Array.set(dest, i, value);}return dest;}}if (pojo instanceof Collection<?>) { //處理集合類型的pojoif (type.isArray()) { //集合轉(zhuǎn)換為數(shù)組Class<?> ctype = type.getComponentType();Collection<Object> src = (Collection<Object>) pojo;int len = src.size();Object dest = Array.newInstance(ctype, len); //創(chuàng)建指定類型和長度的數(shù)組history.put(pojo, dest);int i = 0;for (Object obj : src) {Object value = realize0(obj, ctype, null, history); //將數(shù)組中的元素依次轉(zhuǎn)換為指定類型pojo對象Array.set(dest, i, value);i++;}return dest;} else {Collection<Object> src = (Collection<Object>) pojo;int len = src.size();Collection<Object> dest = createCollection(type, len);history.put(pojo, dest);for (Object obj : src) { //遍歷集合元素,依次轉(zhuǎn)化到目標(biāo)類型的pojo對象Type keyType = getGenericClassByIndex(genericType, 0);Class<?> keyClazz = obj == null ? null : obj.getClass();if (keyType instanceof Class) {keyClazz = (Class<?>) keyType;}Object value = realize0(obj, keyClazz, keyType, history);dest.add(value);}return dest;}}if (pojo instanceof Map<?, ?> && type != null) { //處理Map類型的pojo(JSONObject:JSON對象,實(shí)現(xiàn)了Map接口,也屬于Map的實(shí)例對象,所以會進(jìn)入此處)Object className = ((Map<Object, Object>) pojo).get("class"); //獲取Map中的"class"鍵對應(yīng)的值,是在generalize方法中設(shè)置的(單個(gè)的pojo中設(shè)置的)if (className instanceof String) {try {type = ClassUtils.forName((String) className); //解析的目標(biāo)類的Class類} catch (ClassNotFoundException e) {// ignore}}// special logic for enumif (type.isEnum()) { //目標(biāo)類型為枚舉Object name = ((Map<Object, Object>) pojo).get("name"); //取出枚舉名稱if (name != null) {return Enum.valueOf((Class<Enum>) type, name.toString()); //使用枚舉名,構(gòu)建枚舉對象}}Map<Object, Object> map;// when return type is not the subclass of return type from the signature and not an interfaceif (!type.isInterface() && !type.isAssignableFrom(pojo.getClass())) { //type非接口且pojo不是type的子類型try {map = (Map<Object, Object>) type.newInstance();Map<Object, Object> mapPojo = (Map<Object, Object>) pojo;map.putAll(mapPojo);if (GENERIC_WITH_CLZ) {map.remove("class");}} catch (Exception e) {//ignore errormap = (Map<Object, Object>) pojo; //type類型不為Map時(shí),使用原始的pojo轉(zhuǎn)換}} else {map = (Map<Object, Object>) pojo; //直接強(qiáng)轉(zhuǎn)為Map類型}if (Map.class.isAssignableFrom(type) || type == Object.class) { //解析的目標(biāo)類為Map時(shí)final Map<Object, Object> result;// fix issue#5939Type mapKeyType = getKeyTypeForMap(map.getClass()); //獲取key的泛型參數(shù)對應(yīng)的實(shí)際類型Type typeKeyType = getGenericClassByIndex(genericType, 0); //獲取目標(biāo)類型的泛型參數(shù)的第一個(gè)實(shí)際參數(shù)boolean typeMismatch = mapKeyType instanceof Class //Type為Class實(shí)例時(shí),表明是基本類型或原始類型,如String、int等&& typeKeyType instanceof Class&& !typeKeyType.getTypeName().equals(mapKeyType.getTypeName()); //判斷key、value類型為基本類型或原始類型,且類型相同if (typeMismatch) { //輸入對象的key與目標(biāo)Map的key類型不匹配是,創(chuàng)建新的Mapresult = createMap(new HashMap(0));} else {result = createMap(map); //類型匹配時(shí),直接使用目標(biāo)Map(會轉(zhuǎn)換為具體的Map類型,如:轉(zhuǎn)換為LinkedHashMap類型)}history.put(pojo, result);for (Map.Entry<Object, Object> entry : map.entrySet()) {Type keyType = getGenericClassByIndex(genericType, 0); //獲取泛型參數(shù)列表指定位置的實(shí)際類型Type valueType = getGenericClassByIndex(genericType, 1);Class<?> keyClazz; //獲取key參數(shù)類型對應(yīng)的Classif (keyType instanceof Class) { //基本類型或原始類型(如:int、Boolean、String等)keyClazz = (Class<?>) keyType;} else if (keyType instanceof ParameterizedType) { //參數(shù)化類型(如:List<ArrayList<String>> 是泛型參數(shù),取實(shí)際類型后為ArrayList<String>,實(shí)際參數(shù)屬于參數(shù)類型)keyClazz = (Class<?>) ((ParameterizedType) keyType).getRawType();} else { //keyType為Null時(shí),取條目中key的類型(其它類型,如類型變量類型T、通配符類型?等)keyClazz = entry.getKey() == null ? null : entry.getKey().getClass();}Class<?> valueClazz; //獲取value參數(shù)類型對應(yīng)的Classif (valueType instanceof Class) {valueClazz = (Class<?>) valueType;} else if (valueType instanceof ParameterizedType) {valueClazz = (Class<?>) ((ParameterizedType) valueType).getRawType();} else {valueClazz = entry.getValue() == null ? null : entry.getValue().getClass();}Object key = keyClazz == null ? entry.getKey() : realize0(entry.getKey(), keyClazz, keyType, history); //遞歸調(diào)用,將key轉(zhuǎn)換為目標(biāo)類型的對象Object value = valueClazz == null ? entry.getValue() : realize0(entry.getValue(), valueClazz, valueType, history); //遞歸調(diào)用,將value轉(zhuǎn)換為目標(biāo)類型的對象result.put(key, value);}return result;} else if (type.isInterface()) { //解析的目標(biāo)類為接口時(shí),產(chǎn)生接口對應(yīng)的代理類Object dest = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] {type}, new PojoInvocationHandler(map)); //使用jdk代理機(jī)制為接口創(chuàng)代理對象,并指定處理器PojoInvocationHandler,在接口方法被調(diào)用時(shí),就會觸發(fā)處理器中方法執(zhí)行指定邏輯history.put(pojo, dest);return dest;} else {Object dest = newInstance(type); //構(gòu)造解析的目標(biāo)類的實(shí)例history.put(pojo, dest); //設(shè)置到緩存Map中for (Map.Entry<Object, Object> entry : map.entrySet()) { //遍歷Map中的條目,找到對應(yīng)目標(biāo)對象的屬性,使用反射機(jī)制調(diào)用Method,依次設(shè)置值Object key = entry.getKey();if (key instanceof String) { //只處理key為String的條目String name = (String) key;Object value = entry.getValue();if (value != null) {Method method = getSetterMethod(dest.getClass(), name, value.getClass()); //通過屬性獲取set方法(從緩存中獲取,若沒有則通過反射獲取Method,再設(shè)置到緩存中)Field field = getField(dest.getClass(), name); //獲取屬性對應(yīng)的字段Filed信息if (method != null) {if (!method.isAccessible()) {method.setAccessible(true);}Type ptype = method.getGenericParameterTypes()[0]; //獲取set方法的第一個(gè)參數(shù)類型value = realize0(value, method.getParameterTypes()[0], ptype, history); //將值轉(zhuǎn)換為指定類型的對象try {method.invoke(dest, value); //使用反射機(jī)制,設(shè)置目標(biāo)對象的屬性值} catch (Exception e) {String exceptionDescription = "Failed to set pojo " + dest.getClass().getSimpleName() + " property " + name+ " value " + value + "(" + value.getClass() + "), cause: " + e.getMessage();logger.error(exceptionDescription, e);throw new RuntimeException(exceptionDescription, e);}} else if (field != null) {value = realize0(value, field.getType(), field.getGenericType(), history);try {field.set(dest, value);} catch (IllegalAccessException e) {throw new RuntimeException("Failed to set field " + name + " of pojo " + dest.getClass().getName() + " : " + e.getMessage(), e);}}}}}if (dest instanceof Throwable) { //目標(biāo)對象為異常對象時(shí),設(shè)置異常信息Object message = map.get("message");if (message instanceof String) {try {Field field = Throwable.class.getDeclaredField("detailMessage");if (!field.isAccessible()) {field.setAccessible(true);}field.set(dest, message);} catch (Exception e) {}}}return dest;}}return pojo;}

關(guān)聯(lián)類PojoInvocationHandler分析

類中核心代碼分析

private static class PojoInvocationHandler implements InvocationHandler { //Pojo代理處理器private Map<Object, Object> map; //在創(chuàng)建代理對象時(shí)指定的public PojoInvocationHandler(Map<Object, Object> map) {this.map = map;}@Override@SuppressWarnings("unchecked")public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //為接口生成代理對象,在調(diào)用接口方法時(shí),會回調(diào)該方法if (method.getDeclaringClass() == Object.class) {return method.invoke(map, args);}String methodName = method.getName();Object value = null;if (methodName.length() > 3 && methodName.startsWith("get")) {value = map.get(methodName.substring(3, 4).toLowerCase() + methodName.substring(4)); //截取方法名,獲取屬性名,從map中獲取相應(yīng)的值} else if (methodName.length() > 2 && methodName.startsWith("is")) {value = map.get(methodName.substring(2, 3).toLowerCase() + methodName.substring(3));} else {value = map.get(methodName.substring(0, 1).toLowerCase() + methodName.substring(1));}if (value instanceof Map<?, ?> && !Map.class.isAssignableFrom(method.getReturnType())) { //返回類型非Map時(shí),調(diào)用realize0進(jìn)行轉(zhuǎn)換value = realize0((Map<String, Object>) value, method.getReturnType(), null, new IdentityHashMap<Object, Object>());}return value;}
}
  • 代碼分析:在轉(zhuǎn)換的目標(biāo)類型為接口時(shí)type.isInterface(),使用jdk動態(tài)代理創(chuàng)建接口的代理對象,PojoInvocationHandler為代理對象的調(diào)用處理器,包含了提取屬性的邏輯

問題點(diǎn)答疑

  • 在realize、generalize方法中都包含了參數(shù)Map<Object, Object> history,用途是什么?
    • 解答:在Pojo屬性為復(fù)雜類型時(shí),即需要遞歸轉(zhuǎn)換或解析時(shí),就可以把已經(jīng)處理過的結(jié)果放入Map中,傳遞給下一個(gè)轉(zhuǎn)換或解析。下次處理前,會判斷是否已經(jīng)處理過,處理過的就不再處理。這樣已經(jīng)處理過的類型就不用處理了,提升處理性能。

歸納總結(jié)

  • PojoUtils轉(zhuǎn)換中,簡單類型包含:基本類型、Number、Date、元素為基本類型的數(shù)組、集合類型等。
  • 在類型轉(zhuǎn)換時(shí),會進(jìn)行遞歸調(diào)用,一直解析到位簡單類型為止。
http://aloenet.com.cn/news/46863.html

相關(guān)文章:

  • 如何制作網(wǎng)站app重慶森林電影
  • 重慶政府a(chǎn)pp渝快辦深圳債務(wù)優(yōu)化公司
  • 網(wǎng)站制作要花多少錢百度一下百度網(wǎng)站
  • 旅游電子商務(wù)的三創(chuàng)賽網(wǎng)站建設(shè)鳳山網(wǎng)站seo
  • 鵬牛網(wǎng)做網(wǎng)站怎么樣章魚磁力鏈接引擎
  • H5網(wǎng)站建設(shè)報(bào)價(jià)多少網(wǎng)絡(luò)營銷推廣系統(tǒng)
  • 交互設(shè)計(jì)包含網(wǎng)站設(shè)計(jì)長清區(qū)seo網(wǎng)絡(luò)優(yōu)化軟件
  • 做網(wǎng)站時(shí) 404網(wǎng)頁如何指向作品推廣
  • 網(wǎng)站那個(gè)做的比較好html+css網(wǎng)頁制作成品
  • 用源代碼做網(wǎng)站2020國內(nèi)十大小說網(wǎng)站排名
  • 什么是門戶網(wǎng)站廣告我想自己建立一個(gè)網(wǎng)站
  • 動畫畢業(yè)設(shè)計(jì)代做網(wǎng)站鄭州百度網(wǎng)站優(yōu)化排名
  • 圖片類網(wǎng)站建設(shè)百度推廣年費(fèi)多少錢
  • 搜索引擎網(wǎng)站有哪些windows優(yōu)化大師是哪個(gè)公司的
  • 電子商務(wù)網(wǎng)站建設(shè)問題百度游戲app下載
  • 怎么用視頻做網(wǎng)站背景重慶seo優(yōu)化公司
  • 東營做網(wǎng)站優(yōu)化的公司軟文廣告案例
  • 杭州網(wǎng)站建設(shè)公司官網(wǎng)頁面設(shè)計(jì)漂亮的網(wǎng)站
  • 武漢單位做網(wǎng)站網(wǎng)站建設(shè)優(yōu)化400報(bào)價(jià)
  • wordpress使用手機(jī)號登錄上海網(wǎng)站seoseodian
  • 現(xiàn)在建一個(gè)網(wǎng)站一年費(fèi)用只要幾百元南寧百度首頁優(yōu)化
  • 金華市網(wǎng)站建設(shè)seo網(wǎng)絡(luò)推廣方法
  • 手機(jī)網(wǎng)站如何制作免費(fèi)百度云網(wǎng)盤資源分享網(wǎng)站
  • 一屏展示網(wǎng)站咸寧網(wǎng)站seo
  • 真正永久免費(fèi)網(wǎng)絡(luò)電話seo搜索引擎優(yōu)化原理
  • 網(wǎng)站開發(fā)教程 模板媒體公關(guān)
  • 不良網(wǎng)站代碼怎么查行者seo無敵
  • 網(wǎng)站關(guān)鍵詞優(yōu)化到首頁難度專業(yè)軟文發(fā)稿平臺
  • 柯基寧波seo企業(yè)網(wǎng)絡(luò)推廣
  • 網(wǎng)站建立于網(wǎng)頁設(shè)計(jì)搜索引擎的優(yōu)化和推廣