This commit is contained in:
redkale
2024-09-25 13:58:21 +08:00
parent 3ce56c08df
commit 3e23c9143a
8 changed files with 1071 additions and 162 deletions

View File

@@ -7,7 +7,6 @@ package org.redkale.convert.json;
import java.lang.reflect.*;
import java.util.*;
import org.redkale.asm.AnnotationVisitor;
import org.redkale.asm.ClassWriter;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import org.redkale.asm.FieldVisitor;
@@ -42,30 +41,18 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
}
protected static JsonDynEncoder generateDyncEncoder(
final JsonFactory factory, final Class clazz, final List<AccessibleObject> members) {
final JsonFactory factory, final Class clazz, final List<AccessibleObject> elements) {
final ObjectEncoder selfObjEncoder = factory.createObjectEncoder(clazz);
selfObjEncoder.init(factory);
if (selfObjEncoder.getMembers().length != members.size()) {
selfObjEncoder.init(factory); // 必须执行初始化EnMember内部信息
if (selfObjEncoder.getMembers().length != elements.size()) {
return null; // 存在ignore等定制配置
}
final String supDynName = JsonDynEncoder.class.getName().replace('.', '/');
final String valtypeName = clazz.getName().replace('.', '/');
final String writerName = JsonWriter.class.getName().replace('.', '/');
final String encodeableName = Encodeable.class.getName().replace('.', '/');
final String objEncoderName = ObjectEncoder.class.getName().replace('.', '/');
final String typeDesc = org.redkale.asm.Type.getDescriptor(Type.class);
final String jsonfactoryDesc = org.redkale.asm.Type.getDescriptor(JsonFactory.class);
final String jsonwriterDesc = org.redkale.asm.Type.getDescriptor(JsonWriter.class);
final String writerDesc = org.redkale.asm.Type.getDescriptor(Writer.class);
final String encodeableDesc = org.redkale.asm.Type.getDescriptor(Encodeable.class);
final String objEncoderDesc = org.redkale.asm.Type.getDescriptor(ObjectEncoder.class);
final String valtypeDesc = org.redkale.asm.Type.getDescriptor(clazz);
Map<String, AccessibleObject> mixedNames0 = null;
StringBuilder memberb = new StringBuilder();
for (AccessibleObject element : members) {
StringBuilder elementb = new StringBuilder();
for (AccessibleObject element : elements) {
final String fieldName = factory.readConvertFieldName(clazz, element);
memberb.append(fieldName).append(',');
elementb.append(fieldName).append(',');
final Class fieldType = readGetSetFieldType(element);
if (fieldType != String.class && !fieldType.isPrimitive()) {
if (mixedNames0 == null) {
@@ -78,7 +65,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final String newDynName = "org/redkaledyn/json/_Dyn" + JsonDynEncoder.class.getSimpleName() + "__"
+ clazz.getName().replace('.', '_').replace('$', '_') + "_" + factory.getFeatures() + "_"
+ Utility.md5Hex(memberb.toString()); // tiny必须要加上, 同一个类会有多个字段定制Convert
+ Utility.md5Hex(elementb.toString()); // tiny必须要加上, 同一个类会有多个字段定制Convert
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
@@ -104,12 +91,23 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
} catch (Throwable ex) {
// do nothing
}
final String supDynName = JsonDynEncoder.class.getName().replace('.', '/');
final String valtypeName = clazz.getName().replace('.', '/');
final String writerName = JsonWriter.class.getName().replace('.', '/');
final String encodeableName = Encodeable.class.getName().replace('.', '/');
final String objEncoderName = ObjectEncoder.class.getName().replace('.', '/');
final String typeDesc = org.redkale.asm.Type.getDescriptor(Type.class);
final String jsonfactoryDesc = org.redkale.asm.Type.getDescriptor(JsonFactory.class);
final String jsonwriterDesc = org.redkale.asm.Type.getDescriptor(JsonWriter.class);
final String writerDesc = org.redkale.asm.Type.getDescriptor(Writer.class);
final String encodeableDesc = org.redkale.asm.Type.getDescriptor(Encodeable.class);
final String objEncoderDesc = org.redkale.asm.Type.getDescriptor(ObjectEncoder.class);
final String valtypeDesc = org.redkale.asm.Type.getDescriptor(clazz);
// ------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(
V11,
ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
@@ -120,12 +118,12 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
fv = cw.visitField(ACC_PROTECTED, "objectEncoderSelf", objEncoderDesc, null, null);
fv.visitEnd();
final int membersSize = members.size();
final int membersSize = elements.size();
boolean onlyTwoIntFieldObjectFlag = false; // 只包含两个int字段
boolean onlyOneLatin1FieldObjectFlag = false; // 只包含一个Latin1 String字段
boolean onlyShotIntLongLatin1MoreFieldObjectFlag = true;
int intFieldCount = 0;
for (AccessibleObject element : members) {
for (AccessibleObject element : elements) {
final String fieldName = factory.readConvertFieldName(clazz, element);
fv = cw.visitField(ACC_PROTECTED + ACC_FINAL, fieldName + "FieldBytes", "[B", null, null);
fv.visitEnd();
@@ -170,7 +168,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "(" + jsonfactoryDesc + typeDesc + ")V", false);
for (AccessibleObject element : members) {
for (AccessibleObject element : elements) {
final String fieldName = factory.readConvertFieldName(clazz, element);
// xxxFieldBytes
mv.visitVarInsn(ALOAD, 0);
@@ -204,11 +202,11 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
mv.visitFieldInsn(PUTFIELD, newDynName, fieldName + "FirstFieldChars", "[C");
}
mv.visitInsn(RETURN);
mv.visitMaxs(1 + members.size(), 1 + members.size());
mv.visitMaxs(1 + elements.size(), 1 + elements.size());
mv.visitEnd();
}
{
{ // convertTo 方法
mv = (cw.visitMethod(ACC_PUBLIC, "convertTo", "(" + jsonwriterDesc + valtypeDesc + ")V", null, null));
// mv.setDebug(true);
{ // if (value == null) { out.writeObjectNull(null); return; }
@@ -246,14 +244,14 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
int elementIndex = -1;
final boolean tiny = ConvertFactory.checkTinyFeature(factory.getFeatures());
final boolean nullable = ConvertFactory.checkNullableFeature(factory.getFeatures());
final Class firstType = readGetSetFieldType(members.get(0));
final Class firstType = readGetSetFieldType(elements.get(0));
final boolean mustHadComma = firstType.isPrimitive()
&& (firstType != boolean.class || !tiny || nullable); // byte/short/char/int/float/long/double
if (onlyOneLatin1FieldObjectFlag) {
// out.writeObjectByOnlyOneLatin1FieldValue(messageFirstFieldBytes, value.getMessage());elementIndex++;
elementIndex++;
AccessibleObject element = members.get(elementIndex);
AccessibleObject element = elements.get(elementIndex);
final String fieldName = factory.readConvertFieldName(clazz, element);
final Class fieldType = readGetSetFieldType(element);
@@ -287,12 +285,12 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
maxLocals++;
} else if (onlyTwoIntFieldObjectFlag) {
elementIndex++;
AccessibleObject element1 = members.get(elementIndex);
AccessibleObject element1 = elements.get(elementIndex);
final String fieldName1 = factory.readConvertFieldName(clazz, element1);
final Class fieldType1 = readGetSetFieldType(element1);
elementIndex++;
AccessibleObject element2 = members.get(elementIndex);
AccessibleObject element2 = elements.get(elementIndex);
final String fieldName2 = factory.readConvertFieldName(clazz, element2);
final Class fieldtype2 = readGetSetFieldType(element2);
@@ -346,7 +344,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
INVOKEVIRTUAL, writerName, "writeObjectByOnlyTwoIntFieldValue", "([B[CI[B[CI)V", false);
} else if (onlyShotIntLongLatin1MoreFieldObjectFlag && mustHadComma) {
for (AccessibleObject element : members) {
for (AccessibleObject element : elements) {
elementIndex++;
final String fieldName = factory.readConvertFieldName(clazz, element);
final Class fieldType = readGetSetFieldType(element);
@@ -427,7 +425,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 3);
}
for (AccessibleObject element : members) {
for (AccessibleObject element : elements) {
elementIndex++;
final String fieldName = factory.readConvertFieldName(clazz, element);
final Class fieldType = readGetSetFieldType(element);
@@ -655,7 +653,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
mv.visitMaxs(maxLocals, maxLocals);
mv.visitEnd();
}
{
{ // convertTo 虚拟方法
mv = (cw.visitMethod(
ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC,
"convertTo",

View File

@@ -7,15 +7,38 @@ package org.redkale.convert.pb;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
import org.redkale.asm.Asms;
import org.redkale.asm.ClassWriter;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import org.redkale.asm.FieldVisitor;
import org.redkale.asm.Label;
import org.redkale.asm.MethodVisitor;
import org.redkale.asm.Opcodes;
import static org.redkale.asm.Opcodes.ACC_BRIDGE;
import static org.redkale.asm.Opcodes.ACC_FINAL;
import static org.redkale.asm.Opcodes.ACC_PROTECTED;
import static org.redkale.asm.Opcodes.ACC_PUBLIC;
import static org.redkale.asm.Opcodes.ACC_SUPER;
import static org.redkale.asm.Opcodes.ACC_SYNTHETIC;
import static org.redkale.asm.Opcodes.ALOAD;
import static org.redkale.asm.Opcodes.ASTORE;
import static org.redkale.asm.Opcodes.CHECKCAST;
import static org.redkale.asm.Opcodes.GETFIELD;
import static org.redkale.asm.Opcodes.IFNONNULL;
import static org.redkale.asm.Opcodes.INVOKESPECIAL;
import static org.redkale.asm.Opcodes.INVOKEVIRTUAL;
import static org.redkale.asm.Opcodes.POP;
import static org.redkale.asm.Opcodes.RETURN;
import static org.redkale.asm.Opcodes.V11;
import org.redkale.convert.*;
import org.redkale.convert.ext.*;
import org.redkale.util.AnyValue;
import org.redkale.util.RedkaleClassLoader;
import org.redkale.util.RedkaleException;
import org.redkale.util.Utility;
/**
* 简单对象的PROTOBUF序列化操作类
@@ -26,26 +49,321 @@ import org.redkale.util.RedkaleClassLoader;
* @since 2.8.0
* @param <T> 序列化的数据类型
*/
public abstract class ProtobufDynEncoder<T> implements Encodeable<ProtobufWriter, T> {
public abstract class ProtobufDynEncoder<T> extends ProtobufObjectEncoder<T> {
protected final Class typeClass;
protected final ObjectEncoder<ProtobufWriter, T> objectEncoder;
protected final ObjectEncoder<ProtobufWriter, T> objectEncoderSelf;
protected ProtobufDynEncoder(final ProtobufFactory factory, Type type) {
// 动态字段: protected SimpledCoder xxxSimpledCoder;
// 动态字段: protected EnMember xxxEnMember;
protected ProtobufDynEncoder(final ProtobufFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
super((Class) type);
this.typeClass = (Class) type;
this.factory = factory;
this.objectEncoderSelf = objectEncoderSelf;
this.members = objectEncoderSelf.getMembers();
this.inited = true;
factory.register(type, this);
this.objectEncoder = factory.createObjectEncoder(type);
}
protected static ProtobufDynEncoder generateDyncEncoder(
final ProtobufFactory factory, final Class clazz, final List<AccessibleObject> members) {
@Override
public abstract void convertTo(ProtobufWriter out, T value);
protected static ProtobufDynEncoder generateDyncEncoder(final ProtobufFactory factory, final Class clazz) {
final ObjectEncoder selfObjEncoder = factory.createObjectEncoder(clazz);
selfObjEncoder.init(factory);
if (selfObjEncoder.getMembers().length != members.size()) {
return null; // 存在ignore等定制配置
selfObjEncoder.init(factory); // 必须执行初始化EnMember内部信息
final Map<String, SimpledCoder> simpledCoders = new HashMap<>();
final Map<String, EnMember> otherMembers = new HashMap<>();
StringBuilder elementb = new StringBuilder();
for (EnMember member : selfObjEncoder.getMembers()) {
final String fieldName = member.getAttribute().field();
final Class fieldClass = member.getAttribute().type();
final Type fieldType = member.getAttribute().genericType();
elementb.append(fieldName).append(',');
if (!ProtobufWriter.isSimpleType(fieldClass)
&& !fieldClass.isEnum()
&& !ProtobufWriter.supportSimpleCollectionType(fieldType)) {
if ((member.getEncoder() instanceof SimpledCoder)) {
simpledCoders.put(fieldName, (SimpledCoder) member.getEncoder());
} else {
otherMembers.put(fieldName, member);
}
}
}
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final String newDynName = "org/redkaledyn/pb/_Dyn" + ProtobufDynEncoder.class.getSimpleName() + "__"
+ clazz.getName().replace('.', '_').replace('$', '_') + "_" + factory.getFeatures() + "_"
+ Utility.md5Hex(elementb.toString()); // tiny必须要加上, 同一个类会有多个字段定制Convert
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
ProtobufDynEncoder resultEncoder =
(ProtobufDynEncoder) newClazz.getConstructor(ProtobufFactory.class, Type.class, ObjectEncoder.class)
.newInstance(factory, clazz, selfObjEncoder);
if (!simpledCoders.isEmpty()) {
for (Map.Entry<String, SimpledCoder> en : simpledCoders.entrySet()) {
Field f = newClazz.getDeclaredField(en.getKey() + "SimpledCoder");
f.setAccessible(true);
f.set(resultEncoder, en.getValue());
}
}
if (!otherMembers.isEmpty()) {
for (Map.Entry<String, EnMember> en : otherMembers.entrySet()) {
Field f = newClazz.getDeclaredField(en.getKey() + "EnMember");
f.setAccessible(true);
f.set(resultEncoder, en.getValue());
}
}
return resultEncoder;
} catch (Throwable ex) {
// do nothing
}
final String supDynName = ProtobufDynEncoder.class.getName().replace('.', '/');
final String valtypeName = clazz.getName().replace('.', '/');
final String pbwriterName = ProtobufWriter.class.getName().replace('.', '/');
final String typeDesc = org.redkale.asm.Type.getDescriptor(Type.class);
final String pbfactoryDesc = org.redkale.asm.Type.getDescriptor(ProtobufFactory.class);
final String pbwriterDesc = org.redkale.asm.Type.getDescriptor(ProtobufWriter.class);
final String simpledCoderDesc = org.redkale.asm.Type.getDescriptor(SimpledCoder.class);
final String enMemberDesc = org.redkale.asm.Type.getDescriptor(EnMember.class);
final String objEncoderDesc = org.redkale.asm.Type.getDescriptor(ObjectEncoder.class);
final String objectDesc = org.redkale.asm.Type.getDescriptor(Object.class);
final String valtypeDesc = org.redkale.asm.Type.getDescriptor(clazz);
// ------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
cw.visit(
V11,
ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
newDynName,
"L" + supDynName + "<" + valtypeDesc + ">;",
supDynName,
null);
if (!simpledCoders.isEmpty()) {
for (String key : simpledCoders.keySet()) {
fv = cw.visitField(ACC_PROTECTED, key + "SimpledCoder", simpledCoderDesc, null, null);
fv.visitEnd();
}
}
if (!otherMembers.isEmpty()) {
for (String key : otherMembers.keySet()) {
fv = cw.visitField(ACC_PROTECTED, key + "EnMember", enMemberDesc, null, null);
fv.visitEnd();
}
}
{ // 构造函数
mv = (cw.visitMethod(
ACC_PUBLIC, "<init>", "(" + pbfactoryDesc + typeDesc + objEncoderDesc + ")V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(
INVOKESPECIAL, supDynName, "<init>", "(" + pbfactoryDesc + typeDesc + objEncoderDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(4, 4);
mv.visitEnd();
}
{ // convertTo 方法
mv = (cw.visitMethod(ACC_PUBLIC, "convertTo", "(" + pbwriterDesc + valtypeDesc + ")V", null, null));
// if (value == null) return;
mv.visitVarInsn(ALOAD, 2); // value
Label ifLabel = new Label();
mv.visitJumpInsn(IFNONNULL, ifLabel);
mv.visitInsn(RETURN);
mv.visitLabel(ifLabel);
mv.visitLineNumber(33, ifLabel);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
// ProtobufWriter out = objectWriter(out0, value);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(
INVOKEVIRTUAL,
newDynName,
"objectWriter",
"(" + pbwriterDesc + objectDesc + ")" + pbwriterDesc,
false);
mv.visitVarInsn(ASTORE, 3);
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, pbwriterName, "writeObjectB", "(Ljava/lang/Object;)I", false);
mv.visitInsn(POP);
for (EnMember member : selfObjEncoder.getMembers()) {
final String fieldName = member.getAttribute().field();
final Type fieldType = member.getAttribute().genericType();
final Class fieldClass = member.getAttribute().type();
if (ProtobufWriter.isSimpleType(fieldClass)) {
mv.visitVarInsn(ALOAD, 3); // out
Asms.visitInsn(mv, member.getTag()); // tag
mv.visitVarInsn(ALOAD, 2); // value
if (member.getMethod() != null) {
String mname = member.getMethod().getName();
String mdesc = org.redkale.asm.Type.getMethodDescriptor(member.getMethod());
mv.visitMethodInsn(INVOKEVIRTUAL, valtypeName, mname, mdesc, false);
} else { // field
Field field = member.getField();
String fname = field.getName();
String fdesc = org.redkale.asm.Type.getDescriptor(field.getType());
mv.visitFieldInsn(GETFIELD, valtypeName, fname, fdesc);
}
String fieldDesc = org.redkale.asm.Type.getDescriptor(fieldClass);
mv.visitMethodInsn(INVOKEVIRTUAL, pbwriterName, "writeFieldValue", "(I" + fieldDesc + ")V", false);
} else if (fieldClass.isEnum()) {
mv.visitVarInsn(ALOAD, 3); // out
Asms.visitInsn(mv, member.getTag()); // tag
mv.visitVarInsn(ALOAD, 2); // value
if (member.getMethod() != null) {
String mname = member.getMethod().getName();
String mdesc = org.redkale.asm.Type.getMethodDescriptor(member.getMethod());
mv.visitMethodInsn(INVOKEVIRTUAL, valtypeName, mname, mdesc, false);
} else { // field
Field field = member.getField();
String fname = field.getName();
String fdesc = org.redkale.asm.Type.getDescriptor(field.getType());
mv.visitFieldInsn(GETFIELD, valtypeName, fname, fdesc);
}
mv.visitMethodInsn(INVOKEVIRTUAL, pbwriterName, "writeFieldValue", "(ILjava/lang/Enum;)V", false);
} else if (ProtobufWriter.supportSimpleCollectionType(fieldType)) {
mv.visitVarInsn(ALOAD, 3); // out
Asms.visitInsn(mv, member.getTag()); // tag
mv.visitVarInsn(ALOAD, 2); // value
if (member.getMethod() != null) {
String mname = member.getMethod().getName();
String mdesc = org.redkale.asm.Type.getMethodDescriptor(member.getMethod());
mv.visitMethodInsn(INVOKEVIRTUAL, valtypeName, mname, mdesc, false);
} else { // field
Field field = member.getField();
String fname = field.getName();
String fdesc = org.redkale.asm.Type.getDescriptor(field.getType());
mv.visitFieldInsn(GETFIELD, valtypeName, fname, fdesc);
}
Class componentType = ProtobufWriter.getSimpleCollectionComponentType(fieldType);
String wmethodName = null;
if (componentType == Boolean.class) {
wmethodName = "writeFieldBoolsValue";
} else if (componentType == Byte.class) {
wmethodName = "writeFieldBytesValue";
} else if (componentType == Character.class) {
wmethodName = "writeFieldCharsValue";
} else if (componentType == Short.class) {
wmethodName = "writeFieldShortsValue";
} else if (componentType == Integer.class) {
wmethodName = "writeFieldIntsValue";
} else if (componentType == Float.class) {
wmethodName = "writeFieldFloatsValue";
} else if (componentType == Long.class) {
wmethodName = "writeFieldLongsValue";
} else if (componentType == Double.class) {
wmethodName = "writeFieldDoublesValue";
} else if (componentType == String.class) {
wmethodName = "writeFieldStringValue";
}
mv.visitMethodInsn(INVOKEVIRTUAL, pbwriterName, wmethodName, "(ILjava/util/Collection;)V", false);
} else if (simpledCoders.containsKey(fieldName)) {
mv.visitVarInsn(ALOAD, 3); // out
Asms.visitInsn(mv, member.getTag()); // tag
mv.visitVarInsn(ALOAD, 0); // this
mv.visitFieldInsn(GETFIELD, newDynName, fieldName + "SimpledCoder", simpledCoderDesc);
mv.visitVarInsn(ALOAD, 2); // value
if (member.getMethod() != null) {
String mname = member.getMethod().getName();
String mdesc = org.redkale.asm.Type.getMethodDescriptor(member.getMethod());
mv.visitMethodInsn(INVOKEVIRTUAL, valtypeName, mname, mdesc, false);
} else { // field
Field field = member.getField();
String fname = field.getName();
String fdesc = org.redkale.asm.Type.getDescriptor(field.getType());
mv.visitFieldInsn(GETFIELD, valtypeName, fname, fdesc);
}
mv.visitMethodInsn(
INVOKEVIRTUAL,
pbwriterName,
"writeFieldValue",
"(I" + simpledCoderDesc + objectDesc + ")V",
false);
} else {
mv.visitVarInsn(ALOAD, 3); // out
mv.visitVarInsn(ALOAD, 0); // this
mv.visitFieldInsn(GETFIELD, newDynName, fieldName + "EnMember", enMemberDesc);
mv.visitVarInsn(ALOAD, 2); // value
mv.visitMethodInsn(
INVOKEVIRTUAL,
pbwriterName,
"writeObjectField",
"(" + enMemberDesc + objectDesc + ")V",
false);
}
}
mv.visitVarInsn(ALOAD, 3); // out
mv.visitVarInsn(ALOAD, 2); // value
mv.visitMethodInsn(INVOKEVIRTUAL, pbwriterName, "writeObjectE", "(Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(4, 3);
mv.visitEnd();
}
{ // convertTo 虚拟方法
mv = (cw.visitMethod(
ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC,
"convertTo",
"(" + pbwriterDesc + "Ljava/lang/Object;)V",
null,
null));
// mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, valtypeName);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "convertTo", "(" + pbwriterDesc + valtypeDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Class<ProtobufDynEncoder> newClazz = (Class<ProtobufDynEncoder>)
new ClassLoader(loader) {
public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
try {
ProtobufDynEncoder resultEncoder =
(ProtobufDynEncoder) newClazz.getConstructor(ProtobufFactory.class, Type.class, ObjectEncoder.class)
.newInstance(factory, clazz, selfObjEncoder);
if (!simpledCoders.isEmpty()) {
for (Map.Entry<String, SimpledCoder> en : simpledCoders.entrySet()) {
Field f = newClazz.getDeclaredField(en.getKey() + "SimpledCoder");
f.setAccessible(true);
f.set(resultEncoder, en.getValue());
RedkaleClassLoader.putReflectionField(newClazz.getName(), f);
}
}
if (!otherMembers.isEmpty()) {
for (Map.Entry<String, EnMember> en : otherMembers.entrySet()) {
Field f = newClazz.getDeclaredField(en.getKey() + "EnMember");
f.setAccessible(true);
f.set(resultEncoder, en.getValue());
RedkaleClassLoader.putReflectionField(newClazz.getName(), f);
}
}
return resultEncoder;
} catch (Exception ex) {
throw new RedkaleException(ex);
}
return null;
}
// 字段全部是primitive或String类型且没有泛型的类才能动态生成ProtobufDynEncoder 不支持的返回null
@@ -53,6 +371,10 @@ public abstract class ProtobufDynEncoder<T> implements Encodeable<ProtobufWriter
if (!(type instanceof Class)) {
return null;
}
if (AnyValue.class.isAssignableFrom((Class) type)) {
return null;
}
// 发现有自定义的基础数据类型Encoder就不动态生成ProtobufDynEncoder了
if (factory.loadEncoder(boolean.class) != BoolSimpledCoder.instance) {
return null;
@@ -106,106 +428,14 @@ public abstract class ProtobufDynEncoder<T> implements Encodeable<ProtobufWriter
if (factory.loadEncoder(double[].class) != DoubleArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(String[].class) != StringArraySimpledCoder.instance) {
return null;
}
return generateDyncEncoder(factory, (Class) type);
}
final Class clazz = (Class) type;
List<AccessibleObject> members = null;
Set<String> names = new HashSet<>();
try {
ConvertColumnEntry ref;
RedkaleClassLoader.putReflectionPublicFields(clazz.getName());
for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (factory.isConvertDisabled(field)) {
continue;
}
ref = factory.findRef(clazz, field);
if (ref != null && ref.ignore()) {
continue;
}
if (factory.findFieldCoder(clazz, field.getName()) != null) {
return null;
}
if (!factory.isSimpleMemberType(clazz, field.getGenericType(), field.getType())) {
return null;
}
String name = factory.readConvertFieldName(clazz, field);
if (names.contains(name)) {
continue;
}
names.add(name);
if (members == null) {
members = new ArrayList<>();
}
members.add(field);
}
RedkaleClassLoader.putReflectionPublicMethods(clazz.getName());
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().length() > 2)
&& !(method.getName().startsWith("get")
&& method.getName().length() > 3)) {
continue;
}
if (factory.isConvertDisabled(method)) {
continue;
}
if (method.getParameterTypes().length != 0) {
continue;
}
if (method.getReturnType() == void.class) {
continue;
}
ref = factory.findRef(clazz, method);
if (ref != null && ref.ignore()) {
continue;
}
if (ref != null && ref.fieldFunc() != null) {
return null;
}
if (!factory.isSimpleMemberType(clazz, method.getGenericReturnType(), method.getReturnType())) {
return null;
}
String name = factory.readConvertFieldName(clazz, method);
if (names.contains(name)) {
continue;
}
if (factory.findFieldCoder(clazz, name) != null) {
return null;
}
names.add(name);
if (members == null) {
members = new ArrayList<>();
}
members.add(method);
}
if (members == null) {
return null;
}
factory.sortFieldIndex(clazz, members);
return generateDyncEncoder(factory, clazz, members);
} catch (Exception ex) {
ex.printStackTrace();
return null;
protected static Class readGetSetFieldType(AccessibleObject element) {
if (element instanceof Field) {
return ((Field) element).getType();
}
return ((Method) element).getReturnType();
}
@Override

View File

@@ -16,19 +16,25 @@ import org.redkale.convert.*;
public class ProtobufMapEncoder<K, V> extends MapEncoder<ProtobufWriter, K, V> {
private final boolean enumtostring;
private final int keyTag;
private final int valTag;
public ProtobufMapEncoder(ConvertFactory factory, Type type) {
super(factory, type);
this.enumtostring = ((ProtobufFactory) factory).enumtostring;
this.keyTag = 1 << 3 | ProtobufFactory.wireType(keyEncoder.getType(), enumtostring);
this.valTag = 2 << 3 | ProtobufFactory.wireType(valueEncoder.getType(), enumtostring);
}
@Override
protected void writeMemberValue(ProtobufWriter out, EnMember member, K key, V value, boolean first) {
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
if (member != null) out.writeFieldName(member);
tmp.writeUInt32(1 << 3 | ProtobufFactory.wireType(keyEncoder.getType(), enumtostring));
if (member != null) {
out.writeFieldName(member);
}
tmp.writeTag(keyTag);
keyEncoder.convertTo(tmp, key);
tmp.writeUInt32(2 << 3 | ProtobufFactory.wireType(valueEncoder.getType(), enumtostring));
tmp.writeTag(valTag);
valueEncoder.convertTo(tmp, value);
out.writeLength(tmp.count());
out.writeTo(tmp.toArray());

View File

@@ -5,6 +5,7 @@
*/
package org.redkale.convert.pb;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.util.*;
@@ -1056,7 +1057,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldBoolsValue(int tag, Boolean[] value) {
public void writeFieldValue(int tag, Boolean[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeBools(value);
@@ -1065,7 +1066,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldBytesValue(int tag, Byte[] value) {
public void writeFieldValue(int tag, Byte[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeBytes(value);
@@ -1074,7 +1075,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldCharsValue(int tag, Character[] value) {
public void writeFieldValue(int tag, Character[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeChars(value);
@@ -1083,7 +1084,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldShortsValue(int tag, Short[] value) {
public void writeFieldValue(int tag, Short[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeShorts(value);
@@ -1092,7 +1093,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldIntsValue(int tag, Integer[] value) {
public void writeFieldValue(int tag, Integer[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeInts(value);
@@ -1101,7 +1102,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldFloatsValue(int tag, Float[] value) {
public void writeFieldValue(int tag, Float[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeFloats(value);
@@ -1110,7 +1111,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldLongsValue(int tag, Long[] value) {
public void writeFieldValue(int tag, Long[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeLongs(value);
@@ -1119,7 +1120,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldDoublesValue(int tag, Double[] value) {
public void writeFieldValue(int tag, Double[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeDoubles(value);
@@ -1128,9 +1129,8 @@ public class ProtobufWriter extends Writer implements ByteTuple {
}
@ClassDepends
public void writeFieldStringsValue(int tag, String[] value) {
public void writeFieldValue(int tag, String[] value) {
if (value != null && value.length > 0) {
writeTag(tag);
writeStrings(tag, value);
this.comma = true;
}
@@ -1211,7 +1211,6 @@ public class ProtobufWriter extends Writer implements ByteTuple {
@ClassDepends
public void writeFieldStringsValue(int tag, Collection<String> value) {
if (value != null && !value.isEmpty()) {
writeTag(tag);
writeStrings(tag, value);
this.comma = true;
}
@@ -1233,7 +1232,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
if (enumtostring) {
writeString(value.name());
} else {
writeInt(value.ordinal());
writeUInt32(value.ordinal());
}
this.comma = true;
}
@@ -1494,6 +1493,70 @@ public class ProtobufWriter extends Writer implements ByteTuple {
};
}
public static boolean isSimpleType(Class fieldClass) {
return fieldClass.isPrimitive()
|| fieldClass == Boolean.class
|| fieldClass == Byte.class
|| fieldClass == Character.class
|| fieldClass == Short.class
|| fieldClass == Integer.class
|| fieldClass == Float.class
|| fieldClass == Long.class
|| fieldClass == Double.class
|| fieldClass == String.class
|| fieldClass == boolean[].class
|| fieldClass == byte[].class
|| fieldClass == char[].class
|| fieldClass == short[].class
|| fieldClass == int[].class
|| fieldClass == float[].class
|| fieldClass == long[].class
|| fieldClass == double[].class
|| fieldClass == Boolean[].class
|| fieldClass == Byte[].class
|| fieldClass == Character[].class
|| fieldClass == Short[].class
|| fieldClass == Integer[].class
|| fieldClass == Float[].class
|| fieldClass == Long[].class
|| fieldClass == Double[].class
|| fieldClass == String[].class;
}
public static boolean supportSimpleCollectionType(Type type) {
if (!(type instanceof ParameterizedType)) {
return false;
}
ParameterizedType ptype = (ParameterizedType) type;
if (!(ptype.getRawType() instanceof Class)) {
return false;
}
Type[] ptargs = ptype.getActualTypeArguments();
if (ptargs == null || ptargs.length != 1) {
return false;
}
Class ownerType = (Class) ptype.getRawType();
if (!Collection.class.isAssignableFrom(ownerType)) {
return false;
}
Type componentType = ptargs[0];
return componentType == Boolean.class
|| componentType == Byte.class
|| componentType == Character.class
|| componentType == Short.class
|| componentType == Integer.class
|| componentType == Float.class
|| componentType == Long.class
|| componentType == Double.class
|| componentType == String.class;
}
public static Class getSimpleCollectionComponentType(Type type) {
return supportSimpleCollectionType(type)
? (Class) ((ParameterizedType) type).getActualTypeArguments()[0]
: null;
}
/** see com.google.protobuf.CodedOutputStream **/
protected static int computeInt32SizeNoTag(final int value) {
if (value == 0) {