java分布式环境下,反序列化遇到类型擦除问题,解决思路

来源:互联网 发布:新兵的爆菊经历知乎 编辑:程序博客网 时间:2024/06/10 15:36

前言

公司使用springcloud搭建了一个分布式框架。但是在框架之间调用的时候,如果返回结果的真实类型涉及到泛型,就会遇到类型擦除的问题。这个问题的解决方案是,框架中数据传输时候序列化和反序列化的时候,需要获取数据的真实类型,来进行反序列化。


序列化的方案

1. 使用java的IO进行序列化和反序列化
2.使用json来进行序列化和反序列化
3.使用hessian来进行序列化和反序列化
4.使用dubbo协议来进行序列化和反序列化
虽然有很多序列化和反序列化方案,但是想要写出能够解决泛型擦除问题的代码还是非常困难的。

代码

翻阅大量资料之后,终于在dubbo框架的dubbo-common源码中找到了具体实现。
代码可以参考dubbo-common包,该jar包是阿里的dubbo框架的common,里面有上述所有方案的具体实现。
这里仅仅展示FastJson的实现
FastJsonSerialization.java
/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.common.serialize.support.json;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import com.alibaba.dubbo.common.URL;import com.alibaba.dubbo.common.serialize.ObjectInput;import com.alibaba.dubbo.common.serialize.ObjectOutput;import com.alibaba.dubbo.common.serialize.Serialization;/** * FastJsonSerialization *  * @author william.liangf */public class FastJsonSerialization implements Serialization {    public byte getContentTypeId() {        return 6;    }    public String getContentType() {        return "text/json";    }        public ObjectOutput serialize(URL url, OutputStream output) throws IOException {        return new FastJsonObjectOutput(output);    }    public ObjectInput deserialize(URL url, InputStream input) throws IOException {        return new FastJsonObjectInput(input);    }}

FastJsonObjectOutput.java
/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.common.serialize.support.json;import java.io.IOException;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.io.Writer;import com.alibaba.dubbo.common.serialize.ObjectOutput;import com.alibaba.fastjson.serializer.JSONSerializer;import com.alibaba.fastjson.serializer.SerializeWriter;import com.alibaba.fastjson.serializer.SerializerFeature;/** * JsonObjectOutput *  * @author william.liangf */public class FastJsonObjectOutput implements ObjectOutput {    private final PrintWriter writer;        public FastJsonObjectOutput(OutputStream out) {        this(new OutputStreamWriter(out));    }        public FastJsonObjectOutput(Writer writer) {        this.writer = new PrintWriter(writer);    }    public void writeBool(boolean v) throws IOException {        writeObject(v);    }    public void writeByte(byte v) throws IOException {        writeObject(v);    }    public void writeShort(short v) throws IOException {        writeObject(v);    }    public void writeInt(int v) throws IOException {        writeObject(v);    }    public void writeLong(long v) throws IOException {        writeObject(v);    }    public void writeFloat(float v) throws IOException {        writeObject(v);    }    public void writeDouble(double v) throws IOException {        writeObject(v);    }    public void writeUTF(String v) throws IOException {        writeObject(v);    }    public void writeBytes(byte[] b) throws IOException {        writer.println(new String(b));    }    public void writeBytes(byte[] b, int off, int len) throws IOException {        writer.println(new String(b, off, len));    }    public void writeObject(Object obj) throws IOException {        SerializeWriter out = new SerializeWriter();        JSONSerializer serializer = new JSONSerializer(out);        serializer.config(SerializerFeature.WriteEnumUsingToString, true);        serializer.write(obj);        out.writeTo(writer);        writer.println();        writer.flush();    }    public void flushBuffer() throws IOException {        writer.flush();    }}
FastJsonObjectInput.java
/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.common.serialize.support.json;import java.io.BufferedReader;import java.io.EOFException;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.Reader;import java.lang.reflect.Type;import com.alibaba.dubbo.common.serialize.ObjectInput;import com.alibaba.dubbo.common.utils.PojoUtils;import com.alibaba.fastjson.JSON;/** * JsonObjectInput *  * @author william.liangf */public class FastJsonObjectInput implements ObjectInput {    private final BufferedReader reader;    public FastJsonObjectInput(InputStream in){        this(new InputStreamReader(in));    }    public FastJsonObjectInput(Reader reader){        this.reader = new BufferedReader(reader);    }    public boolean readBool() throws IOException {        try {            return readObject(boolean.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public byte readByte() throws IOException {        try {            return readObject( byte.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public short readShort() throws IOException {        try {            return readObject(short.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public int readInt() throws IOException {        try {            return readObject(int.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public long readLong() throws IOException {        try {            return readObject(long.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public float readFloat() throws IOException {        try {            return readObject(float.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public double readDouble() throws IOException {        try {            return readObject(double.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public String readUTF() throws IOException {        try {            return readObject(String.class);        } catch (ClassNotFoundException e) {            throw new IOException(e.getMessage());        }    }    public byte[] readBytes() throws IOException {        return readLine().getBytes();    }    public Object readObject() throws IOException, ClassNotFoundException {        String json = readLine();        return JSON.parse(json);    }    public <T> T readObject(Class<T> cls) throws IOException, ClassNotFoundException {        String json = readLine();        return JSON.parseObject(json, cls);    }    @SuppressWarnings("unchecked")    public <T> T readObject(Class<T> cls, Type type) throws IOException,ClassNotFoundException    {        Object value = readObject(cls);        return (T) PojoUtils.realize(value, cls, type);    }    private String readLine() throws IOException, EOFException {        String line = reader.readLine();        if(line == null || line.trim().length() == 0) throw new EOFException();        return line;    }}
PojoUtils.java

/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.common.utils;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Proxy;import java.lang.reflect.Type;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.HashMap;import java.util.HashSet;import java.util.Hashtable;import java.util.IdentityHashMap;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import java.util.Properties;import java.util.TreeMap;import java.util.WeakHashMap;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import java.util.concurrent.ConcurrentSkipListMap;/** * PojoUtils. Travel object deeply, and convert complex type to simple type. * <p> * Simple type below will be remained: * <ul> * <li> Primitive Type, also include <b>String</b>, <b>Number</b>(Integer, Long), <b>Date</b> * <li> Array of Primitive Type * <li> Collection, eg: List, Map, Set etc. * </ul> * <p> * Other type will be covert to a map which contains the attributes and value pair of object. *  * @author william.liangf * @author ding.lid */public class PojoUtils {        private static final ConcurrentMap<String, Method>  NAME_METHODS_CACHE = new ConcurrentHashMap<String, Method>();    private static final ConcurrentMap<Class<?>, ConcurrentMap<String, Field>> CLASS_FIELD_CACHE =         new ConcurrentHashMap<Class<?>, ConcurrentMap<String, Field>>();    public static Object[] generalize(Object[] objs) {        Object[] dests = new Object[objs.length];        for (int i = 0; i < objs.length; i ++) {            dests[i] = generalize(objs[i]);        }        return dests;    }    public static Object[] realize(Object[] objs, Class<?>[] types) {        if (objs.length != types.length)            throw new IllegalArgumentException("args.length != types.length");        Object[] dests = new Object[objs.length];        for (int i = 0; i < objs.length; i ++) {            dests[i] = realize(objs[i], types[i]);        }        return dests;    }    public static Object[] realize(Object[] objs, Class<?>[] types, Type[] gtypes) {        if (objs.length != types.length                || objs.length != gtypes.length)            throw new IllegalArgumentException("args.length != types.length");        Object[] dests = new Object[objs.length];        for (int i = 0; i < objs.length; i ++) {            dests[i] = realize(objs[i], types[i], gtypes[i]);        }        return dests;    }    public static Object generalize(Object pojo) {        return generalize(pojo, new IdentityHashMap<Object, Object>());    }    @SuppressWarnings("unchecked")    private static Object generalize(Object pojo, Map<Object, Object> history) {        if (pojo == null) {            return null;        }                if (pojo instanceof Enum<?>) {            return ((Enum<?>)pojo).name();        }        if (pojo.getClass().isArray()         && Enum.class.isAssignableFrom(        pojo.getClass().getComponentType())) {        int len = Array.getLength(pojo);        String[] values = new String[len];        for (int i = 0; i < len; i ++) {        values[i] = ((Enum<?>)Array.get(pojo, i)).name();        }            return values;        }                if (ReflectUtils.isPrimitives(pojo.getClass())) {            return pojo;        }        if (pojo instanceof Class) {            return ((Class)pojo).getName();        }        Object o = history.get(pojo);        if(o != null){            return o;        }        history.put(pojo, pojo);                if (pojo.getClass().isArray()) {            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<?>) {            Collection<Object> src = (Collection<Object>)pojo;            int len = src.size();            Collection<Object> dest = (pojo instanceof List<?>) ? new ArrayList<Object>(len) : new HashSet<Object>(len);            history.put(pojo, dest);            for (Object obj : src) {                dest.add(generalize(obj, history));            }            return dest;        }        if (pojo instanceof Map<?, ?>) {            Map<Object, Object> src = (Map<Object, Object>)pojo;            Map<Object, Object> dest= createMap(src);            history.put(pojo, dest);            for (Map.Entry<Object, Object> obj : src.entrySet()) {            dest.put(generalize(obj.getKey(), history), generalize(obj.getValue(), history));            }            return dest;        }        Map<String, Object> map = new HashMap<String, Object>();        history.put(pojo, map);        map.put("class", pojo.getClass().getName());        for (Method method : pojo.getClass().getMethods()) {            if (ReflectUtils.isBeanPropertyReadMethod(method)) {                try {                    map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method),                            generalize(method.invoke(pojo), history));                } catch (Exception e) {                    throw new RuntimeException(e.getMessage(), e);                }            }        }        // public field        for(Field field : pojo.getClass().getFields()) {            if (ReflectUtils.isPublicInstanceField(field)) {                try {                    Object fieldValue = field.get(pojo);                    // public filed同时也有get/set方法,如果get/set存取的不是前面那个 public field 该如何处理                    if (history.containsKey(pojo)) {                        Object pojoGenerilizedValue = history.get(pojo);                        if (pojoGenerilizedValue instanceof Map                            && ((Map)pojoGenerilizedValue).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;    }        public static Object realize(Object pojo, Class<?> type) {        return realize0(pojo, type, null , new IdentityHashMap<Object, Object>());    }        public static Object realize(Object pojo, Class<?> type, Type genericType) {        return realize0(pojo, type, genericType, new IdentityHashMap<Object, Object>());    }        private static class PojoInvocationHandler implements InvocationHandler {                private Map<Object, Object> map;        public PojoInvocationHandler(Map<Object, Object> map) {            this.map = map;        }        @SuppressWarnings("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));            } 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())) {                value = realize0((Map<String, Object>) value, method.getReturnType(), null, new IdentityHashMap<Object, Object>());            }            return value;        }    }        @SuppressWarnings("unchecked")private static Collection<Object> createCollection(Class<?> type, int len) {    if (type.isAssignableFrom(ArrayList.class)) {    return  new ArrayList<Object>(len);    }    if (type.isAssignableFrom(HashSet.class)) {    return new HashSet<Object>(len);    }    if (! type.isInterface() && ! Modifier.isAbstract(type.getModifiers())) {    try {return (Collection<Object>) type.newInstance();} catch (Exception e) {// ignore}    }    return new ArrayList<Object>();    }    private static Map createMap(Map src) {        Class<? extends Map> cl = src.getClass();        Map result = null;        if (HashMap.class == cl) {            result = new HashMap();        } else if (Hashtable.class == cl) {            result = new Hashtable();        } else if (IdentityHashMap.class == cl) {            result = new IdentityHashMap();        } else if (LinkedHashMap.class == cl) {            result = new LinkedHashMap();        } else if (Properties.class == cl) {            result = new Properties();        } else if (TreeMap.class == cl) {            result = new TreeMap();        } else if (WeakHashMap.class == cl) {            return new WeakHashMap();        } else if (ConcurrentHashMap.class == cl) {            result = new ConcurrentHashMap();        } else if (ConcurrentSkipListMap.class == cl) {            result = new ConcurrentSkipListMap();        } else {            try {                result = cl.newInstance();            } catch (Exception e) { /* ignore */ }            if (result == null) {                try {                    Constructor<?> constructor = cl.getConstructor(Map.class);                    result = (Map)constructor.newInstance(Collections.EMPTY_MAP);                } catch (Exception e) { /* ignore */ }            }        }        if (result == null) {            result = new HashMap<Object, Object>();        }        return result;    }    @SuppressWarnings({ "unchecked", "rawtypes" })    private static Object realize0(Object pojo, Class<?> type, Type genericType, final Map<Object, Object> history) {        if (pojo == null) {            return null;        }                if (type != null && type.isEnum()         && pojo.getClass() == String.class) {    return Enum.valueOf((Class<Enum>)type, (String)pojo);    }        if (ReflectUtils.isPrimitives(pojo.getClass())        && ! (type != null && type.isArray()        && type.getComponentType().isEnum()        && pojo.getClass() == String[].class)) {            return CompatibleTypeUtils.compatibleTypeConvert(pojo, type);        }        Object o = history.get(pojo);                if(o != null){            return o;        }                history.put(pojo, pojo);                if (pojo.getClass().isArray()) {        if (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);                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<?>) {        if (type.isArray()) {        Class<?> ctype = type.getComponentType();                Collection<Object> src = (Collection<Object>)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);                    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) {                    Type keyType = getGenericClassByIndex(genericType, 0);                    Class<?> keyClazz = 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) {        Object className = ((Map<Object, Object>)pojo).get("class");            if (className instanceof String) {                try {                    type = ClassHelper.forName((String)className);                } catch (ClassNotFoundException e) {                    // ignore                }            }            Map<Object, Object> map ;            // 返回值类型不是方法签名类型的子集 并且 不是接口类型            if (! type.isInterface()                    && ! type.isAssignableFrom(pojo.getClass())){                try {                    map = (Map<Object,Object>)type.newInstance();                } catch (Exception e) {                    //ignore error                    map = (Map<Object, Object>)pojo;                }            }else {                map = (Map<Object, Object>)pojo;            }                        if (Map.class.isAssignableFrom(type) || type == Object.class) {            final Map<Object, Object> result = createMap(map);                history.put(pojo, result);            for (Map.Entry<Object, Object> entry : map.entrySet()) {                Type keyType = getGenericClassByIndex(genericType, 0);                Type valueType = getGenericClassByIndex(genericType, 1);                Class<?> keyClazz;                if ( keyType instanceof Class){                    keyClazz = (Class<?>)keyType;                } else {                    keyClazz = entry.getKey() == null ? null : entry.getKey().getClass();                }                Class<?> valueClazz;                    if ( valueType instanceof Class){                        valueClazz = (Class<?>)valueType;                    } else {                        valueClazz = entry.getValue() == null ? null : entry.getValue().getClass() ;                    }                                Object key = keyClazz == null ? entry.getKey() : realize0(entry.getKey(), keyClazz, keyType, history);                Object value = valueClazz == null ? entry.getValue() : realize0(entry.getValue(), valueClazz, valueType, history);                 result.put(key, value);            }        return result;        } else if (type.isInterface()) {            Object dest = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{type}, new PojoInvocationHandler(map));                history.put(pojo, dest);                return dest;            } else {                Object dest = newInstance(type);                history.put(pojo, dest);                for (Map.Entry<Object, Object> entry : map.entrySet()) {                Object key = entry.getKey();                if (key instanceof String) {                    String name = (String) key;                    Object value = entry.getValue();                    if (value != null) {                        Method method = getSetterMethod(dest.getClass(), name, value.getClass());                            Field field = getField(dest.getClass(), name);                        if (method != null) {                            if (! method.isAccessible())                                method.setAccessible(true);                            Type ptype = method.getGenericParameterTypes()[0];                            value = realize0(value, method.getParameterTypes()[0], ptype, history);                            try {                                method.invoke(dest, value);                            } catch (Exception e) {                                e.printStackTrace();                                throw new RuntimeException("Failed to set pojo " + dest.getClass().getSimpleName() + " property " + name                                        + " value " + value + "(" + value.getClass() + "), cause: " + e.getMessage(), e);                            }                        } else if (field != null) {                                value = realize0(value, field.getType(), field.getGenericType(), history);                                try {                                    field.set(dest, value);                                } catch (IllegalAccessException e) {                                    throw new RuntimeException(                                        new StringBuilder(32)                                            .append("Failed to set filed ")                                            .append(name)                                            .append(" of pojo ")                                            .append(dest.getClass().getName())                                            .append( " : " )                                            .append(e.getMessage()).toString(),                                        e);                                }                            }                    }                }                }                if (dest instanceof Throwable) {                    Object message = map.get("message");                    if (message instanceof String) {                        try {                            Field filed = Throwable.class.getDeclaredField("detailMessage");                            if(! filed.isAccessible()) {                                filed.setAccessible(true);                            }                            filed.set(dest, (String) message);                        } catch (Exception e) {                        }                    }                }                return dest;            }        }        return pojo;    }        /**     * 获取范型的类型      * @param genericType     * @param index     * @return List<Person>  返回Person.class ,Map<String,Person> index=0 返回String.class index=1 返回Person.class     */    private static Type getGenericClassByIndex(Type genericType, int index){        Type clazz = null ;        //范型参数转换         if (genericType instanceof ParameterizedType){            ParameterizedType t = (ParameterizedType)genericType;            Type[] types = t.getActualTypeArguments();            clazz = types[index];        }        return clazz;    }        private static Object newInstance(Class<?> cls) {        try {            return cls.newInstance();        } catch (Throwable t) {            try {                Constructor<?>[] constructors = cls.getConstructors();                if (constructors != null && constructors.length == 0) {                    throw new RuntimeException("Illegal constructor: " + cls.getName());                }                Constructor<?> constructor = constructors[0];                if (constructor.getParameterTypes().length > 0) {                    for (Constructor<?> c : constructors) {                        if (c.getParameterTypes().length <                                 constructor.getParameterTypes().length) {                            constructor = c;                            if (constructor.getParameterTypes().length == 0) {                                break;                            }                        }                    }                }                return constructor.newInstance(new Object[constructor.getParameterTypes().length]);            } catch (InstantiationException e) {                throw new RuntimeException(e.getMessage(), e);            } catch (IllegalAccessException e) {                throw new RuntimeException(e.getMessage(), e);            } catch (InvocationTargetException e) {                throw new RuntimeException(e.getMessage(), e);            }        }    }    private static Method getSetterMethod(Class<?> cls, String property, Class<?> valueCls) {        String name = "set" + property.substring(0, 1).toUpperCase() + property.substring(1);        Method method = NAME_METHODS_CACHE.get(cls.getName() + "." + name + "(" +valueCls.getName() + ")");            if(method == null){                try {                method = cls.getMethod(name, valueCls);                } catch (NoSuchMethodException e) {                    for (Method m : cls.getMethods()) {                        if (ReflectUtils.isBeanPropertyWriteMethod(m)                                && m.getName().equals(name)) {                             method = m;                        }                    }                }                if(method != null){                    NAME_METHODS_CACHE.put(cls.getName() + "." + name + "(" +valueCls.getName() + ")", method);                }            }       return method;    }        private static Field getField(Class<?> cls, String fieldName) {        Field result = null;        if (CLASS_FIELD_CACHE.containsKey(cls)             && CLASS_FIELD_CACHE.get(cls).containsKey(fieldName)) {            return CLASS_FIELD_CACHE.get(cls).get(fieldName);        }        try {            result = cls.getField(fieldName);        } catch (NoSuchFieldException e) {            for(Field field : cls.getFields()) {                if (fieldName.equals(field.getName())                     && ReflectUtils.isPublicInstanceField(field)) {                    result = field;                    break;                }            }        }        if (result != null) {            ConcurrentMap<String, Field> fields = CLASS_FIELD_CACHE.get(cls);            if (fields == null) {                fields = new ConcurrentHashMap<String, Field>();                CLASS_FIELD_CACHE.putIfAbsent(cls, fields);            }            fields = CLASS_FIELD_CACHE.get(cls);            fields.putIfAbsent(fieldName, result);        }        return result;    }        public static boolean isPojo(Class<?> cls) {        return ! ReflectUtils.isPrimitives(cls)                && ! Collection.class.isAssignableFrom(cls)                 && ! Map.class.isAssignableFrom(cls);    }}

CompatibleTypeUtils.java
/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.common.utils;import java.lang.reflect.Array;import java.math.BigDecimal;import java.math.BigInteger;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Collection;import java.util.Date;import java.util.HashSet;import java.util.List;import java.util.Set;/** * @author ding.lid */public class CompatibleTypeUtils {        private CompatibleTypeUtils() {    }    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";    /**     * 兼容类型转换。null值是OK的。如果不需要转换,则返回原来的值。     * 进行的兼容类型转换如下:(基本类对应的Wrapper类型不再列出。)     * <ul>     * <li> String -> char, enum, Date     * <li> byte, short, int, long -> byte, short, int, long     * <li> float, double -> float, double     * </ul>     */    @SuppressWarnings({ "unchecked", "rawtypes" })public static Object compatibleTypeConvert(Object value, Class<?> type) {        if(value == null || type == null || type.isAssignableFrom(value.getClass())) {        return value;        }        if(value instanceof String) {            String string = (String) value;            if (char.class.equals(type) || Character.class.equals(type)) {                if(string.length() != 1) {                    throw new IllegalArgumentException(String.format("CAN NOT convert String(%s) to char!" +                            " when convert String to char, the String MUST only 1 char.", string));                }                return string.charAt(0);            } else if(type.isEnum()) {                return Enum.valueOf((Class<Enum>)type, string);            } else if(type == BigInteger.class) {                return new BigInteger(string);            } else if(type == BigDecimal.class) {                return new BigDecimal(string);            } else if(type == Short.class || type == short.class) {                return new Short(string);            } else if(type == Integer.class || type == int.class) {                return new Integer(string);            } else if(type == Long.class || type == long.class) {                return new Long(string);            } else if(type == Double.class || type == double.class) {                return new Double(string);            } else if(type == Float.class || type == float.class) {                return new Float(string);            }  else if(type == Byte.class || type == byte.class) {                return new Byte(string);            } else if(type == Boolean.class || type == boolean.class) {                return new Boolean(string);            } else if(type == Date.class) {                try {                    return new SimpleDateFormat(DATE_FORMAT).parse((String) value);                } catch (ParseException e) {                    throw new IllegalStateException("Failed to parse date " + value + " by format " + DATE_FORMAT + ", cause: " + e.getMessage(), e);                }            } else if (type == Class.class) {                try {                    return ReflectUtils.name2class((String)value);                } catch (ClassNotFoundException e) {                    throw new RuntimeException(e.getMessage(), e);                }            }        } else if(value instanceof Number) {            Number number = (Number) value;            if (type == byte.class || type == Byte.class) {                return number.byteValue();            } else if (type == short.class || type == Short.class) {                return number.shortValue();            } else if (type == int.class || type == Integer.class) {                return number.intValue();            } else if (type == long.class || type == Long.class) {                return number.longValue();            } else if (type == float.class || type == Float.class) {                return number.floatValue();            } else if (type == double.class || type == Double.class) {                return number.doubleValue();            } else if (type == BigInteger.class) {                return BigInteger.valueOf(number.longValue());            } else if (type == BigDecimal.class) {                return BigDecimal.valueOf(number.doubleValue());            } else if (type == Date.class) {                return new Date(number.longValue());            }        } else if(value instanceof Collection) {            Collection collection = (Collection) value;            if (type.isArray()) {                int length = collection.size();                Object array = Array.newInstance(type.getComponentType(), length);                int i = 0;                for (Object item : collection) {                    Array.set(array, i ++, item);                }                return array;            } else if (! type.isInterface()) {                try {                    Collection result = (Collection) type.newInstance();                    result.addAll(collection);                    return result;                } catch (Throwable e) {                }            } else if (type == List.class) {                return new ArrayList<Object>(collection);            } else if (type == Set.class) {                return new HashSet<Object>(collection);            }        } else if(value.getClass().isArray() && Collection.class.isAssignableFrom(type)) {            Collection collection;            if (! type.isInterface()) {                try {                    collection = (Collection) type.newInstance();                } catch (Throwable e) {                    collection = new ArrayList<Object>();                }            } else if (type == Set.class) {                collection = new HashSet<Object>();            } else {                collection = new ArrayList<Object>();            }            int length = Array.getLength(value);            for (int i = 0; i < length; i ++) {                collection.add(Array.get(value, i));            }            return collection;        }        return value;    }}
ReflectUtils.java
/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.common.utils;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.GenericArrayType;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.ParameterizedType;import java.net.URL;import java.security.CodeSource;import java.security.ProtectionDomain;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import java.util.regex.Matcher;import java.util.regex.Pattern;import javassist.CtClass;import javassist.CtConstructor;import javassist.CtMethod;import javassist.NotFoundException;/** * ReflectUtils *  * @author qian.lei */public final class ReflectUtils {    /** * void(V). */public static final char JVM_VOID = 'V';/** * boolean(Z). */public static final char JVM_BOOLEAN = 'Z';/** * byte(B). */public static final char JVM_BYTE = 'B';/** * char(C). */public static final char JVM_CHAR = 'C';/** * double(D). */public static final char JVM_DOUBLE = 'D';/** * float(F). */public static final char JVM_FLOAT = 'F';/** * int(I). */public static final char JVM_INT = 'I';/** * long(J). */public static final char JVM_LONG = 'J';/** * short(S). */public static final char JVM_SHORT = 'S';public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];public static final String JAVA_IDENT_REGEX = "(?:[_$a-zA-Z][_$a-zA-Z0-9]*)";public static final String JAVA_NAME_REGEX = "(?:" + JAVA_IDENT_REGEX + "(?:\\." + JAVA_IDENT_REGEX + ")*)";public static final String CLASS_DESC = "(?:L" + JAVA_IDENT_REGEX   + "(?:\\/" + JAVA_IDENT_REGEX + ")*;)";public static final String ARRAY_DESC  = "(?:\\[+(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "))";public static final String DESC_REGEX = "(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "|" + ARRAY_DESC + ")";public static final Pattern DESC_PATTERN = Pattern.compile(DESC_REGEX);public static final String METHOD_DESC_REGEX = "(?:("+JAVA_IDENT_REGEX+")?\\(("+DESC_REGEX+"*)\\)("+DESC_REGEX+")?)";public static final Pattern METHOD_DESC_PATTERN = Pattern.compile(METHOD_DESC_REGEX);public static final Pattern GETTER_METHOD_DESC_PATTERN = Pattern.compile("get([A-Z][_a-zA-Z0-9]*)\\(\\)(" + DESC_REGEX + ")");public static final Pattern SETTER_METHOD_DESC_PATTERN = Pattern.compile("set([A-Z][_a-zA-Z0-9]*)\\((" + DESC_REGEX + ")\\)V");public static final Pattern IS_HAS_CAN_METHOD_DESC_PATTERN = Pattern.compile("(?:is|has|can)([A-Z][_a-zA-Z0-9]*)\\(\\)Z");private static final ConcurrentMap<String, Class<?>>  DESC_CLASS_CACHE = new ConcurrentHashMap<String, Class<?>>();    private static final ConcurrentMap<String, Class<?>>  NAME_CLASS_CACHE = new ConcurrentHashMap<String, Class<?>>();    private static final ConcurrentMap<String, Method>  Signature_METHODS_CACHE = new ConcurrentHashMap<String, Method>();public static boolean isPrimitives(Class<?> cls) {        if (cls.isArray()) {            return isPrimitive(cls.getComponentType());        }        return isPrimitive(cls);    }    public static boolean isPrimitive(Class<?> cls) {        return cls.isPrimitive() || cls == String.class || cls == Boolean.class || cls == Character.class                 || Number.class.isAssignableFrom(cls) || Date.class.isAssignableFrom(cls);    }public static Class<?> getBoxedClass(Class<?> c) {    if( c == int.class )            c = Integer.class;        else if( c == boolean.class )            c = Boolean.class;        else  if( c == long.class )            c = Long.class;        else if( c == float.class )            c = Float.class;        else if( c == double.class )            c = Double.class;        else if( c == char.class )            c = Character.class;        else if( c == byte.class )            c = Byte.class;        else if( c == short.class )            c = Short.class;    return c;}/** * is compatible. *  * @param c class. * @param o instance. * @return compatible or not. */public static boolean isCompatible(Class<?> c, Object o){boolean pt = c.isPrimitive();if( o == null )return !pt;if( pt ){if( c == int.class )c = Integer.class;else if( c == boolean.class )c = Boolean.class;else  if( c == long.class )c = Long.class;else if( c == float.class )c = Float.class;else if( c == double.class )c = Double.class;else if( c == char.class )c = Character.class;else if( c == byte.class )c = Byte.class;else if( c == short.class )c = Short.class;}if( c == o.getClass() )return true;return c.isInstance(o);}/** * is compatible. *  * @param cs class array. * @param os object array. * @return compatible or not. */public static boolean isCompatible(Class<?>[] cs, Object[] os){int len = cs.length;if( len != os.length ) return false;if( len == 0 ) return true;for(int i=0;i<len;i++)if( !isCompatible(cs[i], os[i]) ) return false;return true;}public static String getCodeBase(Class<?> cls) {    if (cls == null)        return null;    ProtectionDomain domain = cls.getProtectionDomain();    if (domain == null)        return null;    CodeSource source = domain.getCodeSource();    if (source == null)        return null;    URL location = source.getLocation();    if (location == null)            return null;    return location.getFile();}/** * get name. * java.lang.Object[][].class => "java.lang.Object[][]" *  * @param c class. * @return name. */public static String getName(Class<?> c){if( c.isArray() ){StringBuilder sb = new StringBuilder();do{sb.append("[]");c = c.getComponentType();}while( c.isArray() );return c.getName() + sb.toString();}return c.getName();}        public static Class<?> getGenericClass(Class<?> cls) {        return getGenericClass(cls, 0);    }    public static Class<?> getGenericClass(Class<?> cls, int i) {        try {            ParameterizedType parameterizedType = ((ParameterizedType) cls.getGenericInterfaces()[0]);            Object genericClass = parameterizedType.getActualTypeArguments()[i];            if (genericClass instanceof ParameterizedType) { // 处理多级泛型                return (Class<?>) ((ParameterizedType) genericClass).getRawType();            } else if (genericClass instanceof GenericArrayType) { // 处理数组泛型                return (Class<?>) ((GenericArrayType) genericClass).getGenericComponentType();            } else if (((Class)genericClass).isArray()) {                // 在 JDK 7 以上的版本, Foo<int[]> 不再是 GenericArrayType                return ((Class)genericClass).getComponentType();            } else {                return (Class<?>) genericClass;            }        } catch (Throwable e) {            throw new IllegalArgumentException(cls.getName()                    + " generic type undefined!", e);        }    }/** * get method name. * "void do(int)", "void do()", "int do(java.lang.String,boolean)" *  * @param m method. * @return name. */public static String getName(final Method m){StringBuilder ret = new StringBuilder();ret.append(getName(m.getReturnType())).append(' ');ret.append(m.getName()).append('(');Class<?>[] parameterTypes = m.getParameterTypes();for(int i=0;i<parameterTypes.length;i++){if( i > 0 )ret.append(',');ret.append(getName(parameterTypes[i]));}ret.append(')');return ret.toString();}public static String getSignature(String methodName, Class<?>[] parameterTypes) {StringBuilder sb = new StringBuilder(methodName);sb.append("(");if (parameterTypes != null && parameterTypes.length > 0) {boolean first = true;for (Class<?> type : parameterTypes) {if (first) {first = false;} else {sb.append(",");}sb.append(type.getName());}}sb.append(")");return sb.toString();}/** * get constructor name. * "()", "(java.lang.String,int)" *  * @param c constructor. * @return name. */public static String getName(final Constructor<?> c){StringBuilder ret = new StringBuilder("(");Class<?>[] parameterTypes = c.getParameterTypes();for(int i=0;i<parameterTypes.length;i++){if( i > 0 )ret.append(',');ret.append(getName(parameterTypes[i]));}ret.append(')');return ret.toString();}/** * get class desc. * boolean[].class => "[Z" * Object.class => "Ljava/lang/Object;" *  * @param c class. * @return desc. * @throws NotFoundException  */public static String getDesc(Class<?> c){StringBuilder ret = new StringBuilder();while( c.isArray() ){ret.append('[');c = c.getComponentType();}if( c.isPrimitive() ){String t = c.getName();if( "void".equals(t) ) ret.append(JVM_VOID);else if( "boolean".equals(t) ) ret.append(JVM_BOOLEAN);else if( "byte".equals(t) ) ret.append(JVM_BYTE);else if( "char".equals(t) ) ret.append(JVM_CHAR);else if( "double".equals(t) ) ret.append(JVM_DOUBLE);else if( "float".equals(t) ) ret.append(JVM_FLOAT);else if( "int".equals(t) ) ret.append(JVM_INT);else if( "long".equals(t) ) ret.append(JVM_LONG);else if( "short".equals(t) ) ret.append(JVM_SHORT);}else{ret.append('L');ret.append(c.getName().replace('.', '/'));ret.append(';');}return ret.toString();}/** * get class array desc. * [int.class, boolean[].class, Object.class] => "I[ZLjava/lang/Object;" *  * @param cs class array. * @return desc. * @throws NotFoundException  */public static String getDesc(final Class<?>[] cs){if( cs.length == 0 )return "";StringBuilder sb = new StringBuilder(64);for( Class<?> c : cs )sb.append(getDesc(c));return sb.toString();}/** * get method desc. * int do(int arg1) => "do(I)I" * void do(String arg1,boolean arg2) => "do(Ljava/lang/String;Z)V" *  * @param m method. * @return desc. */public static String getDesc(final Method m){StringBuilder ret = new StringBuilder(m.getName()).append('(');Class<?>[] parameterTypes = m.getParameterTypes();for(int i=0;i<parameterTypes.length;i++)ret.append(getDesc(parameterTypes[i]));ret.append(')').append(getDesc(m.getReturnType()));return ret.toString();}/** * get constructor desc. * "()V", "(Ljava/lang/String;I)V" *  * @param c constructor. * @return desc */public static String getDesc(final Constructor<?> c){StringBuilder ret = new StringBuilder("(");Class<?>[] parameterTypes = c.getParameterTypes();for(int i=0;i<parameterTypes.length;i++)ret.append(getDesc(parameterTypes[i]));ret.append(')').append('V');return ret.toString();}/** * get method desc. * "(I)I", "()V", "(Ljava/lang/String;Z)V" *  * @param m method. * @return desc. */public static String getDescWithoutMethodName(Method m){StringBuilder ret = new StringBuilder();ret.append('(');Class<?>[] parameterTypes = m.getParameterTypes();for(int i=0;i<parameterTypes.length;i++)ret.append(getDesc(parameterTypes[i]));ret.append(')').append(getDesc(m.getReturnType()));return ret.toString();}/** * get class desc. * Object.class => "Ljava/lang/Object;" * boolean[].class => "[Z" *  * @param c class. * @return desc. * @throws NotFoundException  */public static String getDesc(final CtClass c) throws NotFoundException{StringBuilder ret = new StringBuilder();if( c.isArray() ){ret.append('[');ret.append(getDesc(c.getComponentType()));}else if( c.isPrimitive() ){String t = c.getName();if( "void".equals(t) ) ret.append(JVM_VOID);else if( "boolean".equals(t) ) ret.append(JVM_BOOLEAN);else if( "byte".equals(t) ) ret.append(JVM_BYTE);else if( "char".equals(t) ) ret.append(JVM_CHAR);else if( "double".equals(t) ) ret.append(JVM_DOUBLE);else if( "float".equals(t) ) ret.append(JVM_FLOAT);else if( "int".equals(t) ) ret.append(JVM_INT);else if( "long".equals(t) ) ret.append(JVM_LONG);else if( "short".equals(t) ) ret.append(JVM_SHORT);}else{ret.append('L');ret.append(c.getName().replace('.','/'));ret.append(';');}return ret.toString();}/** * get method desc. * "do(I)I", "do()V", "do(Ljava/lang/String;Z)V" *  * @param m method. * @return desc. */public static String getDesc(final CtMethod m) throws NotFoundException{StringBuilder ret = new StringBuilder(m.getName()).append('(');CtClass[] parameterTypes = m.getParameterTypes();for(int i=0;i<parameterTypes.length;i++)ret.append(getDesc(parameterTypes[i]));ret.append(')').append(getDesc(m.getReturnType()));return ret.toString();}/** * get constructor desc. * "()V", "(Ljava/lang/String;I)V" *  * @param c constructor. * @return desc */public static String getDesc(final CtConstructor c) throws NotFoundException{StringBuilder ret = new StringBuilder("(");CtClass[] parameterTypes = c.getParameterTypes();for(int i=0;i<parameterTypes.length;i++)ret.append(getDesc(parameterTypes[i]));ret.append(')').append('V');return ret.toString();}/** * get method desc. * "(I)I", "()V", "(Ljava/lang/String;Z)V". *  * @param m method. * @return desc. */public static String getDescWithoutMethodName(final CtMethod m) throws NotFoundException{StringBuilder ret = new StringBuilder();ret.append('(');CtClass[] parameterTypes = m.getParameterTypes();for(int i=0;i<parameterTypes.length;i++)ret.append(getDesc(parameterTypes[i]));ret.append(')').append(getDesc(m.getReturnType()));return ret.toString();}/** * name to desc. * java.util.Map[][] => "[[Ljava/util/Map;" *  * @param name name. * @return desc. */public static String name2desc(String name){StringBuilder sb = new StringBuilder();int c = 0,index = name.indexOf('[');if( index > 0 ){c = ( name.length() - index ) / 2;name = name.substring(0,index);}while( c-- > 0 ) sb.append("[");if( "void".equals(name) ) sb.append(JVM_VOID);else if( "boolean".equals(name) ) sb.append(JVM_BOOLEAN);else if( "byte".equals(name) ) sb.append(JVM_BYTE);else if( "char".equals(name) ) sb.append(JVM_CHAR);else if( "double".equals(name) ) sb.append(JVM_DOUBLE);else if( "float".equals(name) ) sb.append(JVM_FLOAT);else if( "int".equals(name) ) sb.append(JVM_INT);else if( "long".equals(name) ) sb.append(JVM_LONG);else if( "short".equals(name) ) sb.append(JVM_SHORT);else sb.append('L').append(name.replace('.', '/')).append(';');return sb.toString();}/** * desc to name. * "[[I" => "int[][]" *  * @param desc desc. * @return name. */public static String desc2name(String desc){StringBuilder sb = new StringBuilder();int c = desc.lastIndexOf('[') + 1;if( desc.length() == c+1 ){switch( desc.charAt(c) ){case JVM_VOID: { sb.append("void"); break; }case JVM_BOOLEAN: { sb.append("boolean"); break; }case JVM_BYTE: { sb.append("byte"); break; }case JVM_CHAR: { sb.append("char"); break; }case JVM_DOUBLE: { sb.append("double"); break; }case JVM_FLOAT: { sb.append("float"); break; }case JVM_INT: { sb.append("int"); break; }case JVM_LONG: { sb.append("long"); break; }case JVM_SHORT: { sb.append("short"); break; }default:throw new RuntimeException();}}else{sb.append(desc.substring(c+1, desc.length()-1).replace('/','.'));}while( c-- > 0 ) sb.append("[]");return sb.toString();}public static Class<?> forName(String name) {try {return name2class(name);} catch (ClassNotFoundException e) {throw new IllegalStateException("Not found class " + name + ", cause: " + e.getMessage(), e);}}/** * name to class. * "boolean" => boolean.class * "java.util.Map[][]" => java.util.Map[][].class *  * @param name name. * @return Class instance. */public static Class<?> name2class(String name) throws ClassNotFoundException{return name2class(ClassHelper.getClassLoader(), name);}/** * name to class. * "boolean" => boolean.class * "java.util.Map[][]" => java.util.Map[][].class *  * @param cl ClassLoader instance. * @param name name. * @return Class instance. */private static Class<?> name2class(ClassLoader cl, String name) throws ClassNotFoundException{int c = 0, index = name.indexOf('[');if( index > 0 ){c = ( name.length() - index ) / 2;name = name.substring(0, index);}if( c > 0 ){StringBuilder sb = new StringBuilder();while( c-- > 0 )sb.append("[");if( "void".equals(name) ) sb.append(JVM_VOID);else if( "boolean".equals(name) ) sb.append(JVM_BOOLEAN);else if( "byte".equals(name) ) sb.append(JVM_BYTE);else if( "char".equals(name) ) sb.append(JVM_CHAR);else if( "double".equals(name) ) sb.append(JVM_DOUBLE);else if( "float".equals(name) ) sb.append(JVM_FLOAT);else if( "int".equals(name) ) sb.append(JVM_INT);else if( "long".equals(name) ) sb.append(JVM_LONG);else if( "short".equals(name) ) sb.append(JVM_SHORT);else sb.append('L').append(name).append(';'); // "java.lang.Object" ==> "Ljava.lang.Object;"name = sb.toString();}else{if( "void".equals(name) ) return void.class;else if( "boolean".equals(name) ) return boolean.class;else if( "byte".equals(name) ) return byte.class;else if( "char".equals(name) ) return char.class;else if( "double".equals(name) ) return double.class;else if( "float".equals(name) ) return float.class;else if( "int".equals(name) ) return int.class;else if( "long".equals(name) ) return long.class;else if( "short".equals(name) ) return short.class;}if( cl == null )cl = ClassHelper.getClassLoader();Class<?> clazz = NAME_CLASS_CACHE.get(name);        if(clazz == null){            clazz = Class.forName(name, true, cl);            NAME_CLASS_CACHE.put(name, clazz);        }        return clazz;}/** * desc to class. * "[Z" => boolean[].class * "[[Ljava/util/Map;" => java.util.Map[][].class *  * @param desc desc. * @return Class instance. * @throws ClassNotFoundException  */public static Class<?> desc2class(String desc) throws ClassNotFoundException{return desc2class(ClassHelper.getClassLoader(), desc);}/** * desc to class. * "[Z" => boolean[].class * "[[Ljava/util/Map;" => java.util.Map[][].class *  * @param cl ClassLoader instance. * @param desc desc. * @return Class instance. * @throws ClassNotFoundException  */private static Class<?> desc2class(ClassLoader cl, String desc) throws ClassNotFoundException{switch( desc.charAt(0) ){case JVM_VOID: return void.class;case JVM_BOOLEAN: return boolean.class;case JVM_BYTE: return byte.class;case JVM_CHAR: return char.class;case JVM_DOUBLE: return double.class;case JVM_FLOAT: return float.class;case JVM_INT: return int.class;case JVM_LONG: return long.class;case JVM_SHORT: return short.class;case 'L':desc = desc.substring(1, desc.length()-1).replace('/', '.'); // "Ljava/lang/Object;" ==> "java.lang.Object"break;case '[':desc = desc.replace('/', '.');  // "[[Ljava/lang/Object;" ==> "[[Ljava.lang.Object;"break;default:throw new ClassNotFoundException("Class not found: " + desc);}if( cl == null )cl = ClassHelper.getClassLoader();Class<?> clazz = DESC_CLASS_CACHE.get(desc);if(clazz==null){    clazz = Class.forName(desc, true, cl);    DESC_CLASS_CACHE.put(desc, clazz);}return clazz;}/** * get class array instance. *  * @param desc desc. * @return Class class array. * @throws ClassNotFoundException  */public static Class<?>[] desc2classArray(String desc) throws ClassNotFoundException{    Class<?>[] ret = desc2classArray(ClassHelper.getClassLoader(), desc);return ret;}/** * get class array instance. *  * @param cl ClassLoader instance. * @param desc desc. * @return Class[] class array. * @throws ClassNotFoundException  */private static Class<?>[] desc2classArray(ClassLoader cl, String desc) throws ClassNotFoundException{if( desc.length() == 0 )return EMPTY_CLASS_ARRAY;List<Class<?>> cs = new ArrayList<Class<?>>();Matcher m = DESC_PATTERN.matcher(desc);while(m.find())cs.add(desc2class(cl, m.group()));return cs.toArray(EMPTY_CLASS_ARRAY);}/** * 根据方法签名从类中找出方法。 *  * @param clazz 查找的类。 * @param methodName 方法签名,形如method1(int, String)。也允许只给方法名不参数只有方法名,形如method2。 * @return 返回查找到的方法。 * @throws NoSuchMethodException * @throws ClassNotFoundException   * @throws IllegalStateException 给定的方法签名找到多个方法(方法签名中没有指定参数,又有有重载的方法的情况) */public static Method findMethodByMethodSignature(Class<?> clazz, String methodName, String[] parameterTypes)        throws NoSuchMethodException, ClassNotFoundException {    String signature = clazz.getName() + "." + methodName;        if(parameterTypes != null && parameterTypes.length > 0){            signature += StringUtils.join(parameterTypes);        }        Method method = Signature_METHODS_CACHE.get(signature);        if(method != null){            return method;        }    if (parameterTypes == null) {            List<Method> finded = new ArrayList<Method>();            for (Method m : clazz.getMethods()) {                if (m.getName().equals(methodName)) {                    finded.add(m);                }            }            if (finded.isEmpty()) {                throw new NoSuchMethodException("No such method " + methodName + " in class " + clazz);            }            if(finded.size() > 1) {                String msg = String.format("Not unique method for method name(%s) in class(%s), find %d methods.",                        methodName, clazz.getName(), finded.size());                throw new IllegalStateException(msg);            }            method = finded.get(0);        } else {            Class<?>[] types = new Class<?>[parameterTypes.length];            for (int i = 0; i < parameterTypes.length; i ++) {                types[i] = ReflectUtils.name2class(parameterTypes[i]);            }            method = clazz.getMethod(methodName, types);                    }    Signature_METHODS_CACHE.put(signature, method);        return method;}    public static Method findMethodByMethodName(Class<?> clazz, String methodName)    throws NoSuchMethodException, ClassNotFoundException {    return findMethodByMethodSignature(clazz, methodName, null);    }        public static Constructor<?> findConstructor(Class<?> clazz, Class<?> paramType) throws NoSuchMethodException {    Constructor<?> targetConstructor;try {targetConstructor = clazz.getConstructor(new Class<?>[] {paramType});} catch (NoSuchMethodException e) {targetConstructor = null;Constructor<?>[] constructors = clazz.getConstructors();for (Constructor<?> constructor : constructors) {if (Modifier.isPublic(constructor.getModifiers()) && constructor.getParameterTypes().length == 1&& constructor.getParameterTypes()[0].isAssignableFrom(paramType)) {targetConstructor = constructor;break;}}if (targetConstructor == null) {throw e;}}return targetConstructor;    }    /**     * 检查对象是否是指定接口的实现。     * <p>     * 不会触发到指定接口的{@link Class},所以如果ClassLoader中没有指定接口类时,也不会出错。     *      * @param obj 要检查的对象     * @param interfaceClazzName 指定的接口名     * @return 返回{@code true},如果对象实现了指定接口;否则返回{@code false}。     */    public static boolean isInstance(Object obj, String interfaceClazzName) {        for (Class<?> clazz = obj.getClass();                 clazz != null && !clazz.equals(Object.class);                 clazz = clazz.getSuperclass()) {            Class<?>[] interfaces = clazz.getInterfaces();            for (Class<?> itf : interfaces) {                if (itf.getName().equals(interfaceClazzName)) {                    return true;                }            }        }        return false;    }        public static Object getEmptyObject(Class<?> returnType) {        return getEmptyObject(returnType, new HashMap<Class<?>, Object>(), 0);    }        private static Object getEmptyObject(Class<?> returnType, Map<Class<?>, Object> emptyInstances, int level) {        if (level > 2)            return null;        if (returnType == null) {            return null;        } else if (returnType == boolean.class || returnType == Boolean.class) {            return false;        } else if (returnType == char.class || returnType == Character.class) {            return '\0';        } else if (returnType == byte.class || returnType == Byte.class) {            return (byte)0;        } else if (returnType == short.class || returnType == Short.class) {            return (short)0;        } else if (returnType == int.class || returnType == Integer.class) {            return 0;        } else if (returnType == long.class || returnType == Long.class) {            return 0L;        } else if (returnType == float.class || returnType == Float.class) {            return 0F;        } else if (returnType == double.class || returnType == Double.class) {            return 0D;        } else if (returnType.isArray()) {            return Array.newInstance(returnType.getComponentType(), 0);        } else if (returnType.isAssignableFrom(ArrayList.class)) {            return new ArrayList<Object>(0);        } else if (returnType.isAssignableFrom(HashSet.class)) {            return new HashSet<Object>(0);        } else if (returnType.isAssignableFrom(HashMap.class)) {            return new HashMap<Object, Object>(0);        } else if (String.class.equals(returnType)) {            return "";        } else if (! returnType.isInterface()) {            try {                Object value = emptyInstances.get(returnType);                if (value == null) {                    value = returnType.newInstance();                    emptyInstances.put(returnType, value);                }                Class<?> cls = value.getClass();                while (cls != null && cls != Object.class) {                    Field[] fields = cls.getDeclaredFields();                    for (Field field : fields) {                        Object property = getEmptyObject(field.getType(), emptyInstances, level + 1);                        if (property != null) {                            try {                                if (! field.isAccessible()) {                                    field.setAccessible(true);                                }                                field.set(value, property);                            } catch (Throwable e) {                            }                        }                    }                    cls = cls.getSuperclass();                }                return value;            } catch (Throwable e) {                return null;            }        } else {            return null;        }    }    public static boolean isBeanPropertyReadMethod(Method method) {        return method != null            && Modifier.isPublic(method.getModifiers())            && ! Modifier.isStatic(method.getModifiers())            && method.getReturnType() != void.class            && method.getDeclaringClass() != Object.class            && method.getParameterTypes().length == 0            && ((method.getName().startsWith("get") && method.getName().length() > 3)                    || (method.getName().startsWith("is") && method.getName().length() > 2));    }    public static String getPropertyNameFromBeanReadMethod(Method method) {        if (isBeanPropertyReadMethod(method)) {            if (method.getName().startsWith("get")) {                return method.getName().substring(3, 4).toLowerCase()                    + method.getName().substring(4);            }            if (method.getName().startsWith("is")) {                return method.getName().substring(2, 3).toLowerCase()                    + method.getName().substring(3);            }        }        return null;    }    public static boolean isBeanPropertyWriteMethod(Method method) {        return method != null            && Modifier.isPublic(method.getModifiers())            && ! Modifier.isStatic(method.getModifiers())            && method.getDeclaringClass() != Object.class            && method.getParameterTypes().length == 1            && method.getName().startsWith("set")            && method.getName().length() > 3;    }        public static String getPropertyNameFromBeanWriteMethod(Method method) {        if (isBeanPropertyWriteMethod(method)) {            return method.getName().substring(3, 4).toLowerCase()                + method.getName().substring(4);        }        return null;    }    public static boolean isPublicInstanceField(Field field) {        return Modifier.isPublic(field.getModifiers())            && !Modifier.isStatic(field.getModifiers())            && !Modifier.isFinal(field.getModifiers())            && !field.isSynthetic();    }    public static Map<String, Field> getBeanPropertyFields(Class cl) {        Map<String, Field> properties = new HashMap<String, Field>();        for(; cl != null; cl = cl.getSuperclass()) {            Field[] fields = cl.getDeclaredFields();            for(Field field : fields) {                if (Modifier.isTransient(field.getModifiers())                    || Modifier.isStatic(field.getModifiers())) {                    continue;                }                field.setAccessible(true);                properties.put(field.getName(), field);            }        }        return properties;    }    public static Map<String, Method> getBeanPropertyReadMethods(Class cl) {        Map<String, Method> properties = new HashMap<String, Method>();        for(; cl != null; cl = cl.getSuperclass()) {            Method[] methods = cl.getDeclaredMethods();            for(Method method : methods) {                if (isBeanPropertyReadMethod(method)) {                    method.setAccessible(true);                    String property = getPropertyNameFromBeanReadMethod(method);                    properties.put(property, method);                }            }        }        return properties;    }private ReflectUtils(){}}


OK,大功告成。。。。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 驾驶证过期了可副业丢了怎么办 外地人北京驾驶本到期换本怎么办 报考驾照时电话号码填错了怎么办 报考驾照时电话填错了怎么办 邢台开三轮车驾证扣12分怎么办 新c1驾照扣满6分怎么办 b2驾照酒驾降级后再次酒驾怎么办 我b2驾照扣了9分怎么办 开别人的车出了事故怎么办 骑摩托车行驶证年检过期了怎么办 在两个城市车船税交重复了怎么办 车子被撞对方全责不赔钱怎么办 驾驶证暂扣期间该审证了怎么办 号码预约被不小心取消了怎么办 老婆出轨要跟我离婚我不想离怎么办 老婆要离婚我不想离电话拉黑怎么办 驾驶证到期换证体检有色弱怎么办 在长沙雨花区考的驾照丢了怎么办 两个户口注销了一个驾证怎么办 车管所发的初始密码弄丢了怎么办? 网上预约驾照考试密码忘记了怎么办 车是温州牌照掉了行驶证怎么办? 触犯了刑法第80条伪造印章怎么办 使用假行驶证被交警查扣车怎么办 摩托车被交警扣了没行驶证怎么办 摩托车行驶证丢了被交警抓到怎么办 摩托车没有行驶证被交警扣了怎么办 有小车执照要大在执照怎么办 报考的南京驾照不退学费怎么办 驾照报名可以退吗?不退怎么办 科目三学时已满公里数未满怎么办 预约驾照考试收不到验证码怎么办 a2驾照违章被扣24分怎么办 出车祸后划分赔偿对方不鉴字怎么办 驾驶证过期了被交警抓到怎么办 摩托车驾驶证6年到期在增驾怎么办 驾照年检时色盲图过不了怎么办 驾驶证扣12分超过两年怎么办 驾驶证被注销后超过两年怎么办 a2照驾驶证年审过期一个月怎么办 车被别人追尾行驶证过期怎么办