怎么进行网站设计和改版,小学生做网站软件,seo诊断报告示例,做网站的等级保护要多少钱功能概述
PojoUtils是一个工具类#xff0c;能够进行深度遍历#xff0c;将简单类型与复杂类型的对象进行转换#xff0c;在泛化调用时用到#xff08;在泛化调用中#xff0c;主要将Pojo对象与Map对象进行相互转换#xff09;
功能分析
核心类PojoUtils分析
主要成员…功能概述
PojoUtils是一个工具类能够进行深度遍历将简单类型与复杂类型的对象进行转换在泛化调用时用到在泛化调用中主要将Pojo对象与Map对象进行相互转换
功能分析
核心类PojoUtils分析
主要成员变量分析
private static final ConcurrentMapString, Method NAME_METHODS_CACHE new ConcurrentHashMapString, Method(); //方法名与Method的缓存为了减少反射获取Method调用key的值用类名和参数类型拼接如org.apache.dubbo.common.model.Person.setName(java.lang.String)
private static final ConcurrentMapClass?, ConcurrentMapString, Field CLASS_FIELD_CACHE new ConcurrentHashMapClass?, ConcurrentMapString, Field(); //字段所在类Class、字段名、字段信息Filed的缓存主要成员方法分析
generalize将复杂对象转换为简单对象
private static Object generalize(Object pojo, MapObject, Object history) { //pojo对象的成员属性会递归转换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数组int len Array.getLength(pojo);String[] values new String[len];for (int i 0; i len; i) { //枚举数组会转换为String数组数组元素的值为枚举名values[i] ((Enum?) Array.get(pojo, i)).name();}return values;}if (ReflectUtils.isPrimitives(pojo.getClass())) { //基本类型直接返回不做处理return pojo;}if (pojo instanceof Class) { //Class类的实例返回类名称return ((Class) pojo).getName();}Object o history.get(pojo);if (o ! null) {return o;}history.put(pojo, pojo);if (pojo.getClass().isArray()) { //pojo对象为数组类型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对象为集合类型CollectionObject src (CollectionObject) pojo;int len src.size();CollectionObject dest (pojo instanceof List?) ? new ArrayListObject(len) : new HashSetObject(len); //区分出List或Set类型并创建对应的集合实例history.put(pojo, dest);for (Object obj : src) { //遍历集合元素依次将元素进行转换dest.add(generalize(obj, history));}return dest;}if (pojo instanceof Map?, ?) { //pojo对象为Map类型MapObject, Object src (MapObject, Object) pojo;MapObject, Object dest createMap(src); //根据原Map类型创建对应的Map对象history.put(pojo, dest);for (Map.EntryObject, Object obj : src.entrySet()) {dest.put(generalize(obj.getKey(), history), generalize(obj.getValue(), history)); //key、value都可能是pojo对象所以都需要进行转换}return dest;}MapString, Object map new HashMapString, Object();history.put(pojo, map);if (GENERIC_WITH_CLZ) {map.put(class, pojo.getClass().getName()); //设置pojo对象的Class类}for (Method method : pojo.getClass().getMethods()) {if (ReflectUtils.isBeanPropertyReadMethod(method)) { //判断是否读取bean的方法即get/is方法try {/*** 处理步骤* 1从方法名中获取到属性名* 2调用pojo对应的方法获取值并通过generalize转换传入history是做临时缓存若能从history取到则用之* 3将属性名和值设置到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)) { //判断是否是公共的实例字段try {Object fieldValue field.get(pojo);if (history.containsKey(pojo)) {Object pojoGeneralizedValue history.get(pojo); //已经转换过的字段就不再转换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方法的作用是把复杂类型对象转换为简单类型的对象如将Pojo对象转换为Map对象Pojo对象的成员对象若还是复杂类型会递归调用进行转换。
realize将简单对象转换为复杂对象
private static Object realize0(Object pojo, Class? type, Type genericType, final MapObject, Object history) { //将简单类型转换为复杂类型如将Map对象转换为指定类型的pojo对象将Map的属性值通过set方法设置到pojo对象中type为目标类型if (pojo null) {return null;}if (type ! null type.isEnum() pojo.getClass() String.class) { //将String转换为枚举类型return Enum.valueOf((ClassEnum) type, (String) pojo);}if (ReflectUtils.isPrimitives(pojo.getClass()) !(type ! null type.isArray() type.getComponentType().isEnum() pojo.getClass() String[].class)) { //将String数组转换为枚举数组return CompatibleTypeUtils.compatibleTypeConvert(pojo, type);}Object o history.get(pojo); //history当方法在递归调用时会用到用缓存使用if (o ! null) {return o;}history.put(pojo, pojo);if (pojo.getClass().isArray()) { //处理数组类型的pojoif (Collection.class.isAssignableFrom(type)) { //目标类型是集合类型Class? ctype pojo.getClass().getComponentType(); //获取数组元素的类型int len Array.getLength(pojo); //获取数组对应长度Collection dest createCollection(type, 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); //依次将对象转换为目标类型如Map转换为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()) { //集合转换为数组Class? ctype type.getComponentType();CollectionObject src (CollectionObject) pojo;int len src.size();Object dest Array.newInstance(ctype, len); //创建指定类型和长度的数组history.put(pojo, dest);int i 0;for (Object obj : src) {Object value realize0(obj, ctype, null, history); //将数组中的元素依次转换为指定类型pojo对象Array.set(dest, i, value);i;}return dest;} else {CollectionObject src (CollectionObject) pojo;int len src.size();CollectionObject dest createCollection(type, len);history.put(pojo, dest);for (Object obj : src) { //遍历集合元素依次转化到目标类型的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类型的pojoJSONObjectJSON对象实现了Map接口也属于Map的实例对象所以会进入此处Object className ((MapObject, Object) pojo).get(class); //获取Map中的class键对应的值是在generalize方法中设置的单个的pojo中设置的if (className instanceof String) {try {type ClassUtils.forName((String) className); //解析的目标类的Class类} catch (ClassNotFoundException e) {// ignore}}// special logic for enumif (type.isEnum()) { //目标类型为枚举Object name ((MapObject, Object) pojo).get(name); //取出枚举名称if (name ! null) {return Enum.valueOf((ClassEnum) type, name.toString()); //使用枚举名构建枚举对象}}MapObject, 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 (MapObject, Object) type.newInstance();MapObject, Object mapPojo (MapObject, Object) pojo;map.putAll(mapPojo);if (GENERIC_WITH_CLZ) {map.remove(class);}} catch (Exception e) {//ignore errormap (MapObject, Object) pojo; //type类型不为Map时使用原始的pojo转换}} else {map (MapObject, Object) pojo; //直接强转为Map类型}if (Map.class.isAssignableFrom(type) || type Object.class) { //解析的目标类为Map时final MapObject, Object result;// fix issue#5939Type mapKeyType getKeyTypeForMap(map.getClass()); //获取key的泛型参数对应的实际类型Type typeKeyType getGenericClassByIndex(genericType, 0); //获取目标类型的泛型参数的第一个实际参数boolean typeMismatch mapKeyType instanceof Class //Type为Class实例时表明是基本类型或原始类型如String、int等 typeKeyType instanceof Class !typeKeyType.getTypeName().equals(mapKeyType.getTypeName()); //判断key、value类型为基本类型或原始类型且类型相同if (typeMismatch) { //输入对象的key与目标Map的key类型不匹配是创建新的Mapresult createMap(new HashMap(0));} else {result createMap(map); //类型匹配时直接使用目标Map会转换为具体的Map类型如转换为LinkedHashMap类型}history.put(pojo, result);for (Map.EntryObject, Object entry : map.entrySet()) {Type keyType getGenericClassByIndex(genericType, 0); //获取泛型参数列表指定位置的实际类型Type valueType getGenericClassByIndex(genericType, 1);Class? keyClazz; //获取key参数类型对应的Classif (keyType instanceof Class) { //基本类型或原始类型如int、Boolean、String等keyClazz (Class?) keyType;} else if (keyType instanceof ParameterizedType) { //参数化类型如ListArrayListString 是泛型参数取实际类型后为ArrayListString实际参数属于参数类型keyClazz (Class?) ((ParameterizedType) keyType).getRawType();} else { //keyType为Null时取条目中key的类型其它类型如类型变量类型T、通配符类型?等keyClazz entry.getKey() null ? null : entry.getKey().getClass();}Class? valueClazz; //获取value参数类型对应的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); //递归调用将key转换为目标类型的对象Object value valueClazz null ? entry.getValue() : realize0(entry.getValue(), valueClazz, valueType, history); //递归调用将value转换为目标类型的对象result.put(key, value);}return result;} else if (type.isInterface()) { //解析的目标类为接口时产生接口对应的代理类Object dest Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class?[] {type}, new PojoInvocationHandler(map)); //使用jdk代理机制为接口创代理对象并指定处理器PojoInvocationHandler在接口方法被调用时就会触发处理器中方法执行指定逻辑history.put(pojo, dest);return dest;} else {Object dest newInstance(type); //构造解析的目标类的实例history.put(pojo, dest); //设置到缓存Map中for (Map.EntryObject, Object entry : map.entrySet()) { //遍历Map中的条目找到对应目标对象的属性使用反射机制调用Method依次设置值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再设置到缓存中Field field getField(dest.getClass(), name); //获取属性对应的字段Filed信息if (method ! null) {if (!method.isAccessible()) {method.setAccessible(true);}Type ptype method.getGenericParameterTypes()[0]; //获取set方法的第一个参数类型value realize0(value, method.getParameterTypes()[0], ptype, history); //将值转换为指定类型的对象try {method.invoke(dest, value); //使用反射机制设置目标对象的属性值} 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) { //目标对象为异常对象时设置异常信息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;}关联类PojoInvocationHandler分析
类中核心代码分析
private static class PojoInvocationHandler implements InvocationHandler { //Pojo代理处理器private MapObject, Object map; //在创建代理对象时指定的public PojoInvocationHandler(MapObject, Object map) {this.map map;}OverrideSuppressWarnings(unchecked)public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //为接口生成代理对象在调用接口方法时会回调该方法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中获取相应的值} 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时调用realize0进行转换value realize0((MapString, Object) value, method.getReturnType(), null, new IdentityHashMapObject, Object());}return value;}
}代码分析在转换的目标类型为接口时type.isInterface()使用jdk动态代理创建接口的代理对象PojoInvocationHandler为代理对象的调用处理器包含了提取属性的逻辑
问题点答疑
在realize、generalize方法中都包含了参数MapObject, Object history用途是什么 解答在Pojo属性为复杂类型时即需要递归转换或解析时就可以把已经处理过的结果放入Map中传递给下一个转换或解析。下次处理前会判断是否已经处理过处理过的就不再处理。这样已经处理过的类型就不用处理了提升处理性能。
归纳总结
PojoUtils转换中简单类型包含基本类型、Number、Date、元素为基本类型的数组、集合类型等。在类型转换时会进行递归调用一直解析到位简单类型为止。