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

前言

公司使用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,大功告成。。。。