This commit is contained in:
@@ -6,7 +6,6 @@
|
|||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.beans.*;
|
import java.beans.*;
|
||||||
import static org.redkale.convert.ObjectEncoder.TYPEZERO;
|
|
||||||
import org.redkale.util.Creator;
|
import org.redkale.util.Creator;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -66,8 +65,6 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
} else {
|
} else {
|
||||||
clazz = (Class) type;
|
clazz = (Class) type;
|
||||||
}
|
}
|
||||||
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
|
|
||||||
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : TYPEZERO;
|
|
||||||
this.creator = factory.loadCreator(clazz);
|
this.creator = factory.loadCreator(clazz);
|
||||||
|
|
||||||
final Set<DeMember> list = new HashSet();
|
final Set<DeMember> list = new HashSet();
|
||||||
@@ -78,7 +75,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||||
ref = factory.findRef(field);
|
ref = factory.findRef(field);
|
||||||
if (ref != null && ref.ignore()) continue;
|
if (ref != null && ref.ignore()) continue;
|
||||||
Type t = ObjectEncoder.makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
|
Type t = ObjectEncoder.createClassType(field.getGenericType(), this.type);
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
|
||||||
}
|
}
|
||||||
final boolean reversible = factory.isReversible();
|
final boolean reversible = factory.isReversible();
|
||||||
@@ -100,7 +97,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
}
|
}
|
||||||
ref = factory.findRef(method);
|
ref = factory.findRef(method);
|
||||||
if (ref != null && ref.ignore()) continue;
|
if (ref != null && ref.ignore()) continue;
|
||||||
Type t = ObjectEncoder.makeGenericType(method.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes);
|
Type t = ObjectEncoder.createClassType(method.getGenericParameterTypes()[0], this.type);
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
|
||||||
}
|
}
|
||||||
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
||||||
@@ -116,19 +113,19 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
//不存在setter方法
|
//不存在setter方法
|
||||||
try {
|
try {
|
||||||
Field f = clazz.getDeclaredField(constructorField);
|
Field f = clazz.getDeclaredField(constructorField);
|
||||||
Type t = ObjectEncoder.makeGenericType(f.getGenericType(), virGenericTypes, realGenericTypes);
|
Type t = ObjectEncoder.createClassType(f.getGenericType(), this.type);
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, f, null, null), factory.loadDecoder(t)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, f, null, null), factory.loadDecoder(t)));
|
||||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
||||||
char[] fs = constructorField.toCharArray();
|
char[] fs = constructorField.toCharArray();
|
||||||
fs[0] = Character.toUpperCase(fs[0]);
|
fs[0] = Character.toUpperCase(fs[0]);
|
||||||
String mn = new String(fs);
|
String mn = new String(fs);
|
||||||
Method getter = null;
|
Method getter;
|
||||||
try {
|
try {
|
||||||
getter = clazz.getMethod("get" + mn);
|
getter = clazz.getMethod("get" + mn);
|
||||||
} catch (NoSuchMethodException ex) {
|
} catch (NoSuchMethodException ex) {
|
||||||
getter = clazz.getMethod("is" + mn);
|
getter = clazz.getMethod("is" + mn);
|
||||||
}
|
}
|
||||||
Type t = ObjectEncoder.makeGenericType(getter.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes);
|
Type t = ObjectEncoder.createClassType(getter.getGenericParameterTypes()[0], this.type);
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, getter, null), factory.loadDecoder(t)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, getter, null), factory.loadDecoder(t)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,53 +47,178 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
this.members = new EnMember[0];
|
this.members = new EnMember[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
public void init(final Factory factory) {
|
||||||
if (type instanceof Class) {
|
this.factory = factory;
|
||||||
return type;
|
try {
|
||||||
} else if (type instanceof ParameterizedType) {
|
if (type == Object.class) return;
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
||||||
Type[] paramTypes = pt.getActualTypeArguments();
|
final Class clazz = this.typeClass;
|
||||||
final Type[] newTypes = new Type[paramTypes.length];
|
final Set<EnMember> list = new HashSet();
|
||||||
int count = 0;
|
final ConstructorProperties cps = ObjectEncoder.findConstructorProperties(factory.loadCreator(this.typeClass));
|
||||||
for (int i = 0; i < newTypes.length; i++) {
|
try {
|
||||||
newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
|
ConvertColumnEntry ref;
|
||||||
if (paramTypes[i] == newTypes[i]) count++;
|
for (final Field field : clazz.getFields()) {
|
||||||
|
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||||
|
ref = factory.findRef(field);
|
||||||
|
if (ref != null && ref.ignore()) continue;
|
||||||
|
Type t = createClassType(field.getGenericType(), this.type);
|
||||||
|
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
|
||||||
|
}
|
||||||
|
final boolean reversible = factory.isReversible();
|
||||||
|
for (final Method method : clazz.getMethods()) {
|
||||||
|
if (Modifier.isStatic(method.getModifiers())) continue;
|
||||||
|
if (Modifier.isAbstract(method.getModifiers())) continue;
|
||||||
|
if (method.isSynthetic()) continue;
|
||||||
|
if (method.getName().length() < 3) continue;
|
||||||
|
if (method.getName().equals("getClass")) continue;
|
||||||
|
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
|
||||||
|
if (method.getParameterTypes().length != 0) continue;
|
||||||
|
if (method.getReturnType() == void.class) continue;
|
||||||
|
if (reversible && (cps == null || !contains(cps.value(), readGetSetFieldName(method)))) {
|
||||||
|
boolean is = method.getName().startsWith("is");
|
||||||
|
try {
|
||||||
|
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
|
||||||
|
} catch (Exception e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ref = factory.findRef(method);
|
||||||
|
if (ref != null && ref.ignore()) continue;
|
||||||
|
Type t = createClassType(method.getGenericReturnType(), this.type);
|
||||||
|
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
|
||||||
|
}
|
||||||
|
this.members = list.toArray(new EnMember[list.size()]);
|
||||||
|
Arrays.sort(this.members);
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new ConvertException(ex);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
inited = true;
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
if (count == paramTypes.length) return pt;
|
|
||||||
return new ParameterizedType() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type[] getActualTypeArguments() {
|
|
||||||
return newTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getRawType() {
|
|
||||||
return pt.getRawType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getOwnerType() {
|
|
||||||
return pt.getOwnerType();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (realGenericTypes == null) return type;
|
}
|
||||||
if (type instanceof WildcardType) {
|
|
||||||
|
@Override
|
||||||
|
public final void convertTo(W out, T value) {
|
||||||
|
if (value == null) {
|
||||||
|
out.wirteClassName(null);
|
||||||
|
out.writeNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.inited) {
|
||||||
|
synchronized (lock) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value != null && value.getClass() != this.typeClass) {
|
||||||
|
final Class clz = value.getClass();
|
||||||
|
out.wirteClassName(factory.getEntity(clz));
|
||||||
|
factory.loadEncoder(clz).convertTo(out, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.writeObjectB(members.length, value);
|
||||||
|
boolean comma = false;
|
||||||
|
for (EnMember member : members) {
|
||||||
|
comma = member.write(out, comma, value);
|
||||||
|
}
|
||||||
|
out.writeObjectE(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Type getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
static Type createClassType(final Type type, final Type declaringType) {
|
||||||
|
if (TypeToken.isClassType(type)) return type;
|
||||||
|
//存在通配符则declaringType 必须是 ParameterizedType
|
||||||
|
if (!(declaringType instanceof ParameterizedType)) return Object.class;
|
||||||
|
if (type instanceof ParameterizedType) { // e.g. Map<String, String>
|
||||||
|
final ParameterizedType pt = (ParameterizedType) type;
|
||||||
|
final Type[] paramTypes = pt.getActualTypeArguments();
|
||||||
|
for (int i = 0; i < paramTypes.length; i++) {
|
||||||
|
paramTypes[i] = createClassType(paramTypes[i], declaringType);
|
||||||
|
}
|
||||||
|
return TypeToken.createParameterizedType(pt.getOwnerType(), pt.getRawType(), paramTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ParameterizedType declaringPType = (ParameterizedType) declaringType;
|
||||||
|
final Type[] virTypes = ((Class) declaringPType.getRawType()).getTypeParameters();
|
||||||
|
final Type[] desTypes = declaringPType.getActualTypeArguments();
|
||||||
|
if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
||||||
final WildcardType wt = (WildcardType) type;
|
final WildcardType wt = (WildcardType) type;
|
||||||
for (Type f : wt.getUpperBounds()) {
|
for (Type f : wt.getUpperBounds()) {
|
||||||
for (int i = 0; i < virGenericTypes.length; i++) {
|
for (int i = 0; i < virTypes.length; i++) {
|
||||||
if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
|
if (virTypes[i].equals(f)) return desTypes.length <= i ? Object.class : desTypes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (type instanceof TypeVariable) {
|
} else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
||||||
for (int i = 0; i < virGenericTypes.length; i++) {
|
for (int i = 0; i < virTypes.length; i++) {
|
||||||
if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
|
if (virTypes[i].equals(type)) return desTypes.length <= i ? Object.class : desTypes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
||||||
|
// if (type instanceof Class) { //e.g. String
|
||||||
|
// return type;
|
||||||
|
// } else if (type instanceof ParameterizedType) { //e.g. Map<String, String>
|
||||||
|
// final ParameterizedType pt = (ParameterizedType) type;
|
||||||
|
// Type[] paramTypes = pt.getActualTypeArguments();
|
||||||
|
// final Type[] newTypes = new Type[paramTypes.length];
|
||||||
|
// int count = 0;
|
||||||
|
// for (int i = 0; i < newTypes.length; i++) {
|
||||||
|
// newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
|
||||||
|
// if (paramTypes[i] == newTypes[i]) count++;
|
||||||
|
// }
|
||||||
|
// if (count == paramTypes.length) return pt;
|
||||||
|
// return new ParameterizedType() {
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Type[] getActualTypeArguments() {
|
||||||
|
// return newTypes;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Type getRawType() {
|
||||||
|
// return pt.getRawType();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Type getOwnerType() {
|
||||||
|
// return pt.getOwnerType();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// if (realGenericTypes == null) return type;
|
||||||
|
// if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
||||||
|
// final WildcardType wt = (WildcardType) type;
|
||||||
|
// for (Type f : wt.getUpperBounds()) {
|
||||||
|
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||||
|
// if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
||||||
|
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||||
|
// if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return type;
|
||||||
|
// }
|
||||||
|
|
||||||
static boolean contains(String[] values, String value) {
|
static boolean contains(String[] values, String value) {
|
||||||
for (String str : values) {
|
for (String str : values) {
|
||||||
@@ -152,102 +277,4 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
return Attributes.create(clazz, fieldalias, field, getter, setter);
|
return Attributes.create(clazz, fieldalias, field, getter, setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(final Factory factory) {
|
|
||||||
this.factory = factory;
|
|
||||||
try {
|
|
||||||
if (type == Object.class) return;
|
|
||||||
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
|
||||||
final Class clazz = this.typeClass;
|
|
||||||
final Set<EnMember> list = new HashSet();
|
|
||||||
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
|
|
||||||
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : null;
|
|
||||||
if (realGenericTypes != null) {
|
|
||||||
// println(type + "," + Arrays.toString(virGenericTypes) + ", " + Arrays.toString(realGenericTypes));
|
|
||||||
}
|
|
||||||
final ConstructorProperties cps = ObjectEncoder.findConstructorProperties(factory.loadCreator(this.typeClass));
|
|
||||||
try {
|
|
||||||
ConvertColumnEntry ref;
|
|
||||||
for (final Field field : clazz.getFields()) {
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
|
||||||
ref = factory.findRef(field);
|
|
||||||
if (ref != null && ref.ignore()) continue;
|
|
||||||
Type t = makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
|
|
||||||
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
|
|
||||||
}
|
|
||||||
final boolean reversible = factory.isReversible();
|
|
||||||
for (final Method method : clazz.getMethods()) {
|
|
||||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
|
||||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
|
||||||
if (method.isSynthetic()) continue;
|
|
||||||
if (method.getName().length() < 3) continue;
|
|
||||||
if (method.getName().equals("getClass")) continue;
|
|
||||||
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
|
|
||||||
if (method.getParameterTypes().length != 0) continue;
|
|
||||||
if (method.getReturnType() == void.class) continue;
|
|
||||||
if (reversible && (cps == null || !contains(cps.value(), readGetSetFieldName(method)))) {
|
|
||||||
boolean is = method.getName().startsWith("is");
|
|
||||||
try {
|
|
||||||
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
|
|
||||||
} catch (Exception e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref = factory.findRef(method);
|
|
||||||
if (ref != null && ref.ignore()) continue;
|
|
||||||
Type t = makeGenericType(method.getGenericReturnType(), virGenericTypes, realGenericTypes);
|
|
||||||
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
|
|
||||||
}
|
|
||||||
this.members = list.toArray(new EnMember[list.size()]);
|
|
||||||
Arrays.sort(this.members);
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new ConvertException(ex);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
inited = true;
|
|
||||||
synchronized (lock) {
|
|
||||||
lock.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void convertTo(W out, T value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.wirteClassName(null);
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.inited) {
|
|
||||||
synchronized (lock) {
|
|
||||||
try {
|
|
||||||
lock.wait();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (value != null && value.getClass() != this.typeClass) {
|
|
||||||
final Class clz = value.getClass();
|
|
||||||
out.wirteClassName(factory.getEntity(clz));
|
|
||||||
factory.loadEncoder(clz).convertTo(out, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeObjectB(members.length, value);
|
|
||||||
boolean comma = false;
|
|
||||||
for (EnMember member : members) {
|
|
||||||
comma = member.write(out, comma, value);
|
|
||||||
}
|
|
||||||
out.writeObjectE(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Type getType() {
|
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.util;
|
package org.redkale.util;
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.WildcardType;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
|
import java.lang.reflect.GenericArrayType;
|
||||||
|
import java.util.*;
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 获取泛型的Type类
|
* 获取泛型的Type类
|
||||||
*
|
*
|
||||||
* @see http://www.redkale.org
|
* @see http://www.redkale.org
|
||||||
@@ -26,4 +32,162 @@ public abstract class TypeToken<T> {
|
|||||||
public final Type getType() {
|
public final Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断Type是否能确定最终的class, 是则返回true,存在通配符或者不确定类型则返回false。
|
||||||
|
* 例如: Map< String, String > 返回 ture; Map< ? extends Serializable, String > 返回false;
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public final static boolean isClassType(final Type type) {
|
||||||
|
if (type instanceof Class) return true;
|
||||||
|
if (type instanceof WildcardType) return false;
|
||||||
|
if (type instanceof TypeVariable) return false;
|
||||||
|
if (type instanceof GenericArrayType) return isClassType(((GenericArrayType) type).getGenericComponentType());
|
||||||
|
if (!(type instanceof ParameterizedType)) return false; //只能是null了
|
||||||
|
final ParameterizedType ptype = (ParameterizedType) type;
|
||||||
|
if (ptype.getOwnerType() != null && !isClassType(ptype.getOwnerType())) return false;
|
||||||
|
if (!isClassType(ptype.getRawType())) return false;
|
||||||
|
for (Type t : ptype.getActualTypeArguments()) {
|
||||||
|
if (!isClassType(t)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态创建 ParameterizedType
|
||||||
|
*
|
||||||
|
* @param ownerType0
|
||||||
|
* @param rawType0
|
||||||
|
* @param actualTypeArguments0
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Type createParameterizedType(final Type ownerType0, final Type rawType0, final Type... actualTypeArguments0) {
|
||||||
|
if (ownerType0 == null && rawType0 instanceof Class) {
|
||||||
|
int count = 0;
|
||||||
|
for (Type t : actualTypeArguments0) {
|
||||||
|
if (isClassType(t)) count++;
|
||||||
|
}
|
||||||
|
if (count == actualTypeArguments0.length) return createParameterizedType((Class) rawType0, actualTypeArguments0);
|
||||||
|
}
|
||||||
|
return new ParameterizedType() {
|
||||||
|
private final Class<?> rawType = (Class<?>) rawType0;
|
||||||
|
|
||||||
|
private final Type ownerType = ownerType0;
|
||||||
|
|
||||||
|
private final Type[] actualTypeArguments = actualTypeArguments0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type[] getActualTypeArguments() {
|
||||||
|
return actualTypeArguments.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getRawType() {
|
||||||
|
return rawType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getOwnerType() {
|
||||||
|
return ownerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Arrays.hashCode(actualTypeArguments) ^ Objects.hashCode(rawType) ^ Objects.hashCode(ownerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof ParameterizedType)) return false;
|
||||||
|
final ParameterizedType that = (ParameterizedType) o;
|
||||||
|
if (this == that) return true;
|
||||||
|
return Objects.equals(ownerType, that.getOwnerType())
|
||||||
|
&& Objects.equals(rawType, that.getRawType())
|
||||||
|
&& Arrays.equals(actualTypeArguments, that.getActualTypeArguments());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (ownerType != null) sb.append((ownerType instanceof Class) ? (((Class) ownerType).getName()) : ownerType.toString()).append(".");
|
||||||
|
sb.append(rawType.getName());
|
||||||
|
|
||||||
|
if (actualTypeArguments != null && actualTypeArguments.length > 0) {
|
||||||
|
sb.append("<");
|
||||||
|
boolean first = true;
|
||||||
|
for (Type t : actualTypeArguments) {
|
||||||
|
if (!first) sb.append(", ");
|
||||||
|
sb.append(t.getTypeName());
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
sb.append(">");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Type createParameterizedType(final Class rawType, final Type... actualTypeArguments) {
|
||||||
|
ClassLoader loader = TypeToken.class.getClassLoader();
|
||||||
|
String newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + System.currentTimeMillis();
|
||||||
|
for (;;) {
|
||||||
|
try {
|
||||||
|
Class.forName(newDynName.replace('/', '.'));
|
||||||
|
newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + Math.abs(System.nanoTime());
|
||||||
|
} catch (Exception ex) { //异常说明类不存在
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClassWriter cw = new ClassWriter(0);
|
||||||
|
FieldVisitor fv;
|
||||||
|
MethodVisitor mv;
|
||||||
|
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, "java/lang/Object", null);
|
||||||
|
String rawTypeDesc = org.objectweb.asm.Type.getDescriptor(rawType);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(rawTypeDesc.substring(0, rawTypeDesc.length() - 1)).append('<');
|
||||||
|
for (Type c : actualTypeArguments) {
|
||||||
|
sb.append(getClassTypeDescriptor(c));
|
||||||
|
}
|
||||||
|
sb.append(">;");
|
||||||
|
{
|
||||||
|
fv = cw.visitField(ACC_PUBLIC, "field", rawTypeDesc, sb.toString(), null);
|
||||||
|
fv.visitEnd();
|
||||||
|
}
|
||||||
|
{//构造方法
|
||||||
|
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mv.visitMaxs(1, 1);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
cw.visitEnd();
|
||||||
|
byte[] bytes = cw.toByteArray();
|
||||||
|
Class<?> newClazz = new ClassLoader(loader) {
|
||||||
|
public final Class<?> loadClass(String name, byte[] b) {
|
||||||
|
return defineClass(name, b, 0, b.length);
|
||||||
|
}
|
||||||
|
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||||
|
try {
|
||||||
|
return newClazz.getField("field").getGenericType();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharSequence getClassTypeDescriptor(Type type) {
|
||||||
|
if (!isClassType(type)) throw new IllegalArgumentException(type + " not a class type");
|
||||||
|
if (type instanceof Class) return org.objectweb.asm.Type.getDescriptor((Class) type);
|
||||||
|
final ParameterizedType pt = (ParameterizedType) type;
|
||||||
|
CharSequence rawTypeDesc = getClassTypeDescriptor(pt.getRawType());
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(rawTypeDesc.subSequence(0, rawTypeDesc.length() - 1)).append('<');
|
||||||
|
for (Type c : pt.getActualTypeArguments()) {
|
||||||
|
sb.append(getClassTypeDescriptor(c));
|
||||||
|
}
|
||||||
|
sb.append(">;");
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user