This commit is contained in:
redkale
2024-09-25 14:53:52 +08:00
parent 3e23c9143a
commit 133c280dc2
12 changed files with 106 additions and 65 deletions

View File

@@ -360,6 +360,7 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
}
}
objout.writeObjectE(value);
offerWriter(out, objout);
}
// ---------------------------------- 可定制方法 ----------------------------------
@@ -375,6 +376,10 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
return out;
}
protected void offerWriter(W parent, W out) {
// do nothing
}
// ---------------------------------------------------------------------------------
protected void setTag(EnMember member, int tag) {
member.tag = tag;

View File

@@ -28,16 +28,20 @@ import org.redkale.util.*;
* @param <T> 序列化的数据类型
*/
@SuppressWarnings("unchecked")
public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
public abstract class JsonDynEncoder<T> extends ObjectEncoder<JsonWriter, T> {
protected final Class typeClass;
protected final ObjectEncoder<JsonWriter, T> objectEncoder;
protected final ObjectEncoder<JsonWriter, T> objectEncoderSelf;
protected JsonDynEncoder(final JsonFactory factory, Type type) {
protected JsonDynEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
super(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 JsonDynEncoder generateDyncEncoder(
@@ -70,11 +74,8 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
JsonDynEncoder resultEncoder =
(JsonDynEncoder) newClazz.getDeclaredConstructor(JsonFactory.class, Type.class)
.newInstance(factory, clazz);
Field selfField = newClazz.getDeclaredField("objectEncoderSelf");
selfField.setAccessible(true);
selfField.set(resultEncoder, selfObjEncoder);
(JsonDynEncoder) newClazz.getConstructor(JsonFactory.class, Type.class, ObjectEncoder.class)
.newInstance(factory, clazz, selfObjEncoder);
if (mixedNames != null) {
for (Map.Entry<String, AccessibleObject> en : mixedNames.entrySet()) {
Field f = newClazz.getDeclaredField(en.getKey() + "Encoder");
@@ -116,8 +117,6 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
supDynName,
null);
fv = cw.visitField(ACC_PROTECTED, "objectEncoderSelf", objEncoderDesc, null, null);
fv.visitEnd();
final int membersSize = elements.size();
boolean onlyTwoIntFieldObjectFlag = false; // 只包含两个int字段
boolean onlyOneLatin1FieldObjectFlag = false; // 只包含一个Latin1 String字段
@@ -161,12 +160,19 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
onlyShotIntLongLatin1MoreFieldObjectFlag = false; // 字段个数必须大于1
}
{ // 构造函数
mv = (cw.visitMethod(ACC_PUBLIC, "<init>", "(" + jsonfactoryDesc + typeDesc + ")V", null, null));
mv = (cw.visitMethod(
ACC_PUBLIC, "<init>", "(" + jsonfactoryDesc + typeDesc + objEncoderDesc + ")V", null, null));
// mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "(" + jsonfactoryDesc + typeDesc + ")V", false);
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(
INVOKESPECIAL,
supDynName,
"<init>",
"(" + jsonfactoryDesc + typeDesc + objEncoderDesc + ")V",
false);
for (AccessibleObject element : elements) {
final String fieldName = factory.readConvertFieldName(clazz, element);
@@ -684,12 +690,8 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
newClazz, newDynName.replace('/', '.'), JsonFactory.class, Type.class);
try {
JsonDynEncoder resultEncoder =
(JsonDynEncoder) newClazz.getDeclaredConstructor(JsonFactory.class, Type.class)
.newInstance(factory, clazz);
Field selfField = newClazz.getDeclaredField("objectEncoderSelf");
selfField.setAccessible(true);
selfField.set(resultEncoder, selfObjEncoder);
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), selfField);
(JsonDynEncoder) newClazz.getConstructor(JsonFactory.class, Type.class, ObjectEncoder.class)
.newInstance(factory, clazz, selfObjEncoder);
if (mixedNames != null) {
for (Map.Entry<String, AccessibleObject> en : mixedNames.entrySet()) {
Field f = newClazz.getDeclaredField(en.getKey() + "Encoder");

View File

@@ -47,10 +47,11 @@ public class ProtobufArrayEncoder<T> extends ArrayEncoder<ProtobufWriter, T> {
} else if (item instanceof CharSequence) {
encoder.convertTo(out, item);
} else {
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
ProtobufWriter tmp = out.pollChild();
encoder.convertTo(tmp, item);
out.writeLength(tmp.count());
out.writeTo(tmp.toArray());
out.offerChild(tmp);
}
}
}

View File

@@ -47,10 +47,11 @@ public class ProtobufCollectionEncoder<T> extends CollectionEncoder<ProtobufWrit
} else if (item instanceof CharSequence) {
componentEncoder.convertTo(out, item);
} else {
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
ProtobufWriter tmp = out.pollChild();
componentEncoder.convertTo(tmp, item);
out.writeLength(tmp.count());
out.writeTo(tmp.toArray());
out.offerChild(tmp);
}
}
}

View File

@@ -4,9 +4,7 @@
*/
package org.redkale.convert.pb;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
@@ -17,22 +15,7 @@ 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 static org.redkale.asm.Opcodes.*;
import org.redkale.convert.*;
import org.redkale.convert.ext.*;
import org.redkale.util.AnyValue;
@@ -59,7 +42,7 @@ public abstract class ProtobufDynEncoder<T> extends ProtobufObjectEncoder<T> {
// 动态字段: protected EnMember xxxEnMember;
protected ProtobufDynEncoder(final ProtobufFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
protected ProtobufDynEncoder(ProtobufFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
super((Class) type);
this.typeClass = (Class) type;
this.factory = factory;
@@ -431,13 +414,6 @@ public abstract class ProtobufDynEncoder<T> extends ProtobufObjectEncoder<T> {
return generateDyncEncoder(factory, (Class) type);
}
protected static Class readGetSetFieldType(AccessibleObject element) {
if (element instanceof Field) {
return ((Field) element).getType();
}
return ((Method) element).getReturnType();
}
@Override
public Type getType() {
return typeClass;

View File

@@ -28,7 +28,7 @@ public class ProtobufMapEncoder<K, V> extends MapEncoder<ProtobufWriter, K, V> {
@Override
protected void writeMemberValue(ProtobufWriter out, EnMember member, K key, V value, boolean first) {
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
ProtobufWriter tmp = out.pollChild();
if (member != null) {
out.writeFieldName(member);
}
@@ -38,5 +38,6 @@ public class ProtobufMapEncoder<K, V> extends MapEncoder<ProtobufWriter, K, V> {
valueEncoder.convertTo(tmp, value);
out.writeLength(tmp.count());
out.writeTo(tmp.toArray());
out.offerChild(tmp);
}
}

View File

@@ -34,8 +34,15 @@ public class ProtobufObjectEncoder<T> extends ObjectEncoder<ProtobufWriter, T> {
@Override
protected ProtobufWriter objectWriter(ProtobufWriter out, T value) {
if (out.count() > out.initOffset) {
return new ProtobufWriter(out, out.getFeatures()).configFieldFunc(out);
return out.pollChild().configParentFunc(out);
}
return out;
}
@Override
protected void offerWriter(ProtobufWriter parent, ProtobufWriter out) {
if (parent != out) {
parent.offerChild(out);
}
}
}

View File

@@ -47,10 +47,11 @@ public class ProtobufStreamEncoder<T> extends StreamEncoder<ProtobufWriter, T> {
if (item instanceof CharSequence) {
componentEncoder.convertTo(out, item);
} else {
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
ProtobufWriter tmp = out.pollChild();
componentEncoder.convertTo(tmp, item);
out.writeUInt32(tmp.count());
out.writeTo(tmp.toArray());
out.offerChild(tmp);
}
}
}

View File

@@ -23,6 +23,8 @@ public class ProtobufWriter extends Writer implements ByteTuple {
"redkale.convert.protobuf.writer.buffer.defsize",
Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
private static final int CHILD_SIZE = 8;
private static final int TENTHOUSAND_MAX = 10001;
private static final byte[][] TENTHOUSAND_UINT_BYTES = new byte[TENTHOUSAND_MAX][];
@@ -69,11 +71,13 @@ public class ProtobufWriter extends Writer implements ByteTuple {
protected ProtobufWriter parent;
protected ProtobufWriter(ProtobufWriter parent, int features) {
private ArrayDeque<ProtobufWriter> childWriters;
protected ProtobufWriter(ProtobufWriter parent) {
this();
this.parent = parent;
this.features = features;
if (parent != null) {
this.features = parent.features;
this.enumtostring = parent.enumtostring;
}
}
@@ -88,6 +92,15 @@ public class ProtobufWriter extends Writer implements ByteTuple {
return this;
}
protected ProtobufWriter configParentFunc(ProtobufWriter parent) {
this.parent = parent;
if (parent != null) {
this.features = parent.features;
this.enumtostring = parent.enumtostring;
}
return this;
}
protected ProtobufWriter configFieldFunc(ProtobufWriter out) {
if (out == null) {
return this;
@@ -116,6 +129,12 @@ public class ProtobufWriter extends Writer implements ByteTuple {
@Override
protected boolean recycle() {
super.recycle();
this.parent = null;
this.mapFieldFunc = null;
this.objFieldFunc = null;
this.objExtFunc = null;
this.features = 0;
this.enumtostring = false;
this.count = 0;
this.initOffset = 0;
if (this.content.length > DEFAULT_SIZE) {
@@ -124,6 +143,27 @@ public class ProtobufWriter extends Writer implements ByteTuple {
return true;
}
public final ProtobufWriter pollChild() {
Queue<ProtobufWriter> queue = this.childWriters;
if (queue == null) {
this.childWriters = new ArrayDeque<>(CHILD_SIZE);
queue = this.childWriters;
}
ProtobufWriter result = queue.poll();
if (result == null) {
result = new ProtobufWriter();
}
return result.configFieldFunc(this);
}
public final void offerChild(final ProtobufWriter child) {
Queue<ProtobufWriter> queue = this.childWriters;
if (child != null && queue != null && queue.size() < CHILD_SIZE) {
child.recycle();
queue.offer(child);
}
}
@Override
public byte[] content() {
return content;
@@ -270,7 +310,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
return length;
} else {
final Class type = obj.getClass();
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
ProtobufWriter tmp = pollChild();
if (type == boolean[].class) {
for (boolean item : (boolean[]) obj) {
tmp.writeBoolean(item);
@@ -405,6 +445,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
int length = tmp.count();
writeLength(length);
writeTo(tmp.toArray());
offerChild(tmp);
return length;
}
}
@@ -1309,11 +1350,12 @@ public class ProtobufWriter extends Writer implements ByteTuple {
if (arrayEncoder.simple) {
if (((Object[]) value).length < 1) {
this.writeFieldName(member);
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
ProtobufWriter tmp = pollChild();
arrayEncoder.convertTo(tmp, member, (Object[]) value);
// int length = tmp.count();
// this.writeUInt32(length);
this.writeTo(tmp.toArray());
offerChild(tmp);
}
} else {
arrayEncoder.convertTo(this, member, (Object[]) value);
@@ -1323,10 +1365,11 @@ public class ProtobufWriter extends Writer implements ByteTuple {
if (collectionEncoder.simple) {
if (!((Collection) value).isEmpty()) {
this.writeFieldName(member);
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
ProtobufWriter tmp = pollChild();
collectionEncoder.convertTo(tmp, member, (Collection) value);
this.writeLength(tmp.count());
this.writeTo(tmp.toArray());
offerChild(tmp);
}
} else {
collectionEncoder.convertTo(this, member, (Collection) value);
@@ -1335,10 +1378,11 @@ public class ProtobufWriter extends Writer implements ByteTuple {
ProtobufStreamEncoder streamEncoder = (ProtobufStreamEncoder) encoder;
if (streamEncoder.simple) {
this.writeFieldName(member);
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
ProtobufWriter tmp = pollChild();
streamEncoder.convertTo(tmp, member, (Stream) value);
this.writeLength(tmp.count());
this.writeTo(tmp.toArray());
offerChild(tmp);
} else {
streamEncoder.convertTo(this, member, (Stream) value);
}

View File

@@ -6,6 +6,7 @@
package org.redkale.test.convert;
import java.lang.reflect.Type;
import org.redkale.convert.ObjectEncoder;
import org.redkale.convert.json.*;
/** @author zhangjx */
@@ -15,8 +16,8 @@ public class _DyncFortuneJsonEncoder extends JsonDynEncoder<Fortune> {
protected final byte[] messageCommaFieldBytes = ",\"message\":".getBytes();
public _DyncFortuneJsonEncoder(JsonFactory factory, Type type) {
super(factory, type);
public _DyncFortuneJsonEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
super(factory, type, objectEncoderSelf);
}
@Override
@@ -26,7 +27,7 @@ public class _DyncFortuneJsonEncoder extends JsonDynEncoder<Fortune> {
return;
}
if (!out.isExtFuncEmpty()) {
objectEncoder.convertTo(out, value);
objectEncoderSelf.convertTo(out, value);
return;
}

View File

@@ -6,6 +6,7 @@
package org.redkale.test.convert;
import java.lang.reflect.Type;
import org.redkale.convert.ObjectEncoder;
import org.redkale.convert.json.*;
/** @author zhangjx */
@@ -15,8 +16,8 @@ public class _DyncMessageJsonEncoder extends JsonDynEncoder<Message> {
protected final byte[] messageCommaFieldBytes = ",\"message\":".getBytes();
public _DyncMessageJsonEncoder(JsonFactory factory, Type type) {
super(factory, type);
public _DyncMessageJsonEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
super(factory, type, objectEncoderSelf);
}
@Override
@@ -26,7 +27,7 @@ public class _DyncMessageJsonEncoder extends JsonDynEncoder<Message> {
return;
}
if (!out.isExtFuncEmpty()) {
objectEncoder.convertTo(out, value);
objectEncoderSelf.convertTo(out, value);
return;
}

View File

@@ -6,6 +6,7 @@
package org.redkale.test.convert;
import java.lang.reflect.Type;
import org.redkale.convert.ObjectEncoder;
import org.redkale.convert.json.*;
/** @author zhangjx */
@@ -15,8 +16,8 @@ public class _DyncWorldJsonEncoder extends JsonDynEncoder<World> {
protected final byte[] randomNumberFieldBytes = ",\"randomNumber\":".getBytes();
public _DyncWorldJsonEncoder(JsonFactory factory, Type type) {
super(factory, type);
public _DyncWorldJsonEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
super(factory, type, objectEncoderSelf);
}
@Override
@@ -26,7 +27,7 @@ public class _DyncWorldJsonEncoder extends JsonDynEncoder<World> {
return;
}
if (!out.isExtFuncEmpty()) {
objectEncoder.convertTo(out, value);
objectEncoderSelf.convertTo(out, value);
return;
}