This commit is contained in:
wentch
2015-12-18 16:24:47 +08:00
parent 773647be33
commit 366fc22c70
3 changed files with 333 additions and 145 deletions

View File

@@ -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)));
} }
} }

View File

@@ -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) + '}';
}
} }

View File

@@ -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&#60; String, String &#62; 返回 ture; Map&#60; ? extends Serializable, String &#62; 返回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;
}
} }