From e4562183cf45c0c5f77c446350da6b89ccf49687 Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 11 Oct 2016 20:45:36 +0800 Subject: [PATCH] bug fixed for issue #849 . improved TypeRerence Performance. --- .../com/alibaba/fastjson/TypeReference.java | 34 +++++++++++++++++-- .../fastjson/util/ParameterizedTypeImpl.java | 15 ++++++++ .../alibaba/json/bvt/TypeReferenceTest10.java | 28 +++++++++++++++ .../alibaba/json/bvt/TypeReferenceTest11.java | 33 ++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/alibaba/json/bvt/TypeReferenceTest10.java create mode 100644 src/test/java/com/alibaba/json/bvt/TypeReferenceTest11.java diff --git a/src/main/java/com/alibaba/fastjson/TypeReference.java b/src/main/java/com/alibaba/fastjson/TypeReference.java index 374c6a62ec..d8252a46ed 100755 --- a/src/main/java/com/alibaba/fastjson/TypeReference.java +++ b/src/main/java/com/alibaba/fastjson/TypeReference.java @@ -3,6 +3,8 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import com.alibaba.fastjson.util.ParameterizedTypeImpl; @@ -22,6 +24,8 @@ * parameters, such as {@code Class} or {@code List}. */ public class TypeReference { + static ConcurrentMap, ConcurrentMap>> classTypeCache + = new ConcurrentHashMap, ConcurrentMap>>(16, 0.75f, 1); protected final Type type; @@ -44,7 +48,8 @@ protected TypeReference(){ * @param actualTypeArguments */ protected TypeReference(Type... actualTypeArguments){ - Type superClass = getClass().getGenericSuperclass(); + Class thisClass = this.getClass(); + Type superClass = thisClass.getGenericSuperclass(); ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0]; Type rawType = argType.getRawType(); @@ -59,7 +64,32 @@ protected TypeReference(Type... actualTypeArguments){ } } } - type = new ParameterizedTypeImpl(argTypes, this.getClass(), rawType); + + if (actualTypeArguments.length == 1 && argTypes.length == 1) { + ConcurrentMap> classCache = classTypeCache.get(thisClass); + if (classCache == null) { + classTypeCache.putIfAbsent(thisClass, new ConcurrentHashMap>(16, 0.75f, 1)); + classCache = classTypeCache.get(thisClass); + } + + ConcurrentMap typeCached = classCache.get(argType); + if (typeCached == null) { + classCache.putIfAbsent(argType, new ConcurrentHashMap(16, 0.75f, 1)); + typeCached = classCache.get(argType); + } + + Type actualTypeArgument = actualTypeArguments[0]; + + Type cachedType = typeCached.get(actualTypeArgument); + if (cachedType == null) { + typeCached.putIfAbsent(actualTypeArgument, actualTypeArgument); + cachedType = typeCached.get(actualTypeArgument); + } + + type = cachedType; + } else { + type = new ParameterizedTypeImpl(argTypes, thisClass, rawType); + } } /** diff --git a/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java b/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java index a5cb33fcd4..7612d27415 100755 --- a/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java +++ b/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java @@ -2,6 +2,7 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.Arrays; public class ParameterizedTypeImpl implements ParameterizedType { @@ -27,4 +28,18 @@ public Type getRawType() { return rawType; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ParameterizedTypeImpl that = (ParameterizedTypeImpl) o; + + // Probably incorrect - comparing Object[] arrays with Arrays.equals + if (!Arrays.equals(actualTypeArguments, that.actualTypeArguments)) return false; + if (ownerType != null ? !ownerType.equals(that.ownerType) : that.ownerType != null) return false; + return rawType != null ? rawType.equals(that.rawType) : that.rawType == null; + + } } diff --git a/src/test/java/com/alibaba/json/bvt/TypeReferenceTest10.java b/src/test/java/com/alibaba/json/bvt/TypeReferenceTest10.java new file mode 100644 index 0000000000..eb9d791a73 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/TypeReferenceTest10.java @@ -0,0 +1,28 @@ +package com.alibaba.json.bvt; + +import com.alibaba.fastjson.TypeReference; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.lang.reflect.Type; + +/** + * Created by wenshao on 2016/10/11. + */ +public class TypeReferenceTest10 extends TestCase { + public void test_same() throws Exception { + Type type1 = getType(); + Type type2 = getType(); + + assertEquals(type1, type2); + assertSame(type1, type2); + } + + Type getType() { + return new TypeReference>() {}.getType(); + } + + public static class Model { + public T value; + } +} diff --git a/src/test/java/com/alibaba/json/bvt/TypeReferenceTest11.java b/src/test/java/com/alibaba/json/bvt/TypeReferenceTest11.java new file mode 100644 index 0000000000..1d670c6a28 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/TypeReferenceTest11.java @@ -0,0 +1,33 @@ +package com.alibaba.json.bvt; + +import com.alibaba.fastjson.TypeReference; +import junit.framework.TestCase; + +import java.lang.reflect.Type; + +/** + * Created by wenshao on 2016/10/11. + */ +public class TypeReferenceTest11 extends TestCase { + public void test_same() throws Exception { + Type type1 = getType(Integer.class); + Type type2 = getType(Integer.class); + + assertEquals(type1, type2); + assertSame(type1, type2); + } + + Type getType(Type type) { + return new TypeReference>(type) {}.getType(); + } + + public static class Model { + public T value; + } + + public static class Response { + public T data; + } + + +}