diff --git a/pom.xml b/pom.xml index a963000..8125ab1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.github.yezhihao protostar - 1.0.5.RELEASE + 2.0.0.RELEASE jar Protostar @@ -50,13 +50,13 @@ org.slf4j slf4j-simple - 1.7.30 + 1.7.31 test org.slf4j slf4j-api - 1.7.30 + 1.7.31 provided diff --git a/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java b/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java index e77d018..ece7b6e 100644 --- a/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java +++ b/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java @@ -1,9 +1,9 @@ package io.github.yezhihao.protostar; import io.github.yezhihao.protostar.annotation.Message; +import io.github.yezhihao.protostar.schema.RuntimeSchema; import io.github.yezhihao.protostar.util.ClassUtils; -import java.beans.Introspector; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -14,7 +14,7 @@ import java.util.Map; */ public class DefaultLoadStrategy extends LoadStrategy { - private Map>> typeClassMapping = new HashMap(140); + private Map>> typeClassMapping = new HashMap(140); public DefaultLoadStrategy() { } @@ -26,33 +26,32 @@ public class DefaultLoadStrategy extends LoadStrategy { if (message != null) { int[] values = message.value(); for (int typeId : values) - loadSchema(typeClassMapping, typeId, type); + loadRuntimeSchema(typeClassMapping, typeId, type); } } - Introspector.flushCaches(); } @Override - public Schema getSchema(Class typeClass, Integer version) { - Map> schemas = typeClassMapping.get(typeClass.getName()); + public RuntimeSchema getRuntimeSchema(Class typeClass, Integer version) { + Map> schemas = typeClassMapping.get(typeClass.getName()); if (schemas == null) { - schemas = loadSchema(typeClassMapping, typeClass); + schemas = loadRuntimeSchema(typeClassMapping, typeClass); } if (schemas == null) return null; - return (Schema) schemas.get(version); + return (RuntimeSchema) schemas.get(version); } @Override - public Map> getSchema(Class typeClass) { - Map> schemas = typeClassMapping.get(typeClass.getName()); + public Map> getRuntimeSchema(Class typeClass) { + Map> schemas = typeClassMapping.get(typeClass.getName()); if (schemas == null) { - schemas = loadSchema(typeClassMapping, typeClass); + schemas = loadRuntimeSchema(typeClassMapping, typeClass); } if (schemas == null) return null; - HashMap> result = new HashMap<>(schemas.size()); - for (Map.Entry> entry : schemas.entrySet()) { - result.put(entry.getKey(), (Schema) entry.getValue()); + HashMap> result = new HashMap<>(schemas.size()); + for (Map.Entry> entry : schemas.entrySet()) { + result.put(entry.getKey(), (RuntimeSchema) entry.getValue()); } return result; } diff --git a/src/main/java/io/github/yezhihao/protostar/FieldFactory.java b/src/main/java/io/github/yezhihao/protostar/FieldFactory.java index 00cc2f8..5f7a260 100644 --- a/src/main/java/io/github/yezhihao/protostar/FieldFactory.java +++ b/src/main/java/io/github/yezhihao/protostar/FieldFactory.java @@ -10,7 +10,6 @@ import io.github.yezhihao.protostar.schema.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.beans.PropertyDescriptor; import java.nio.ByteBuffer; import java.time.LocalDateTime; @@ -23,13 +22,13 @@ public abstract class FieldFactory { protected static Logger log = LoggerFactory.getLogger(FieldFactory.class.getSimpleName()); public static boolean EXPLAIN = false; - public static BasicField create(Field field, PropertyDescriptor property) { - return create(field, property, null); + public static BasicField create(Field field, java.lang.reflect.Field f) { + return create(field, f, null); } - public static BasicField create(Field field, PropertyDescriptor property, Schema schema) { + public static BasicField create(Field field, java.lang.reflect.Field f, Schema schema) { DataType dataType = field.type(); - Class typeClass = property.getPropertyType(); + Class typeClass = f.getType(); Schema fieldSchema; switch (dataType) { @@ -63,7 +62,7 @@ public abstract class FieldFactory { if (schema != null) { fieldSchema = ObjectSchema.getInstance(schema); } else { - Convert convert = property.getReadMethod().getAnnotation(Convert.class); + Convert convert = f.getAnnotation(Convert.class); fieldSchema = ConvertSchema.getInstance(convert.converter()); } break; @@ -71,7 +70,7 @@ public abstract class FieldFactory { fieldSchema = CollectionSchema.getInstance(schema); break; case MAP: - Convert convert = property.getReadMethod().getAnnotation(Convert.class); + Convert convert = f.getAnnotation(Convert.class); fieldSchema = ConvertSchema.getInstance(convert.converter()); break; default: @@ -82,19 +81,19 @@ public abstract class FieldFactory { BasicField result; if (EXPLAIN) { if (field.lengthSize() > 0) { - result = new DynamicLengthField.Logger(field, property, fieldSchema); + result = new DynamicLengthField.Logger(field, f, fieldSchema); } else if (field.length() > 0) { - result = new FixedLengthField.Logger(field, property, fieldSchema); + result = new FixedLengthField.Logger(field, f, fieldSchema); } else { - result = new FixedField.Logger(field, property, fieldSchema); + result = new FixedField.Logger(field, f, fieldSchema); } } else { if (field.lengthSize() > 0) { - result = new DynamicLengthField(field, property, fieldSchema); + result = new DynamicLengthField(field, f, fieldSchema); } else if (field.length() > 0) { - result = new FixedLengthField(field, property, fieldSchema); + result = new FixedLengthField(field, f, fieldSchema); } else { - result = new FixedField(field, property, fieldSchema); + result = new FixedField(field, f, fieldSchema); } } return result; diff --git a/src/main/java/io/github/yezhihao/protostar/IdStrategy.java b/src/main/java/io/github/yezhihao/protostar/IdStrategy.java index a82a41d..e6bfdd8 100644 --- a/src/main/java/io/github/yezhihao/protostar/IdStrategy.java +++ b/src/main/java/io/github/yezhihao/protostar/IdStrategy.java @@ -5,11 +5,6 @@ import io.github.yezhihao.protostar.field.BasicField; import io.github.yezhihao.protostar.schema.RuntimeSchema; import io.netty.buffer.ByteBuf; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.util.*; @@ -54,11 +49,11 @@ public abstract class IdStrategy { if (schema != null) return (Schema) schema; - List properties = findFieldProperties(typeClass); - if (properties.isEmpty()) + List fs = findFields(typeClass); + if (fs.isEmpty()) return null; - List fieldList = findFields(root, properties); + List fieldList = findFields(root, fs); BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]); Arrays.sort(fields); @@ -67,57 +62,44 @@ public abstract class IdStrategy { return (Schema) schema; } - protected static List findFieldProperties(Class typeClass) { - BeanInfo beanInfo; - try { - beanInfo = Introspector.getBeanInfo(typeClass); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors(); - List result = new ArrayList<>(properties.length); + protected static List findFields(Class typeClass) { + java.lang.reflect.Field[] fields = typeClass.getDeclaredFields(); + List result = new ArrayList<>(fields.length); - for (PropertyDescriptor property : properties) { - Method readMethod = property.getReadMethod(); - - if (readMethod != null) { - if (readMethod.isAnnotationPresent(Field.class)) { - result.add(property); - } + for (java.lang.reflect.Field f : fields) { + if (f.isAnnotationPresent(Field.class)) { + result.add(f); } } return result; } - protected static List findFields(Map root, List properties) { - List fields = new ArrayList<>(properties.size()); + protected static List findFields(Map root, List fs) { + List fields = new ArrayList<>(fs.size()); - for (PropertyDescriptor property : properties) { - Method readMethod = property.getReadMethod(); - - Field field = readMethod.getDeclaredAnnotation(Field.class); + for (java.lang.reflect.Field f : fs) { + Field field = f.getDeclaredAnnotation(Field.class); if (field != null) { - fillField(root, fields, property, field); + fillField(root, fields, f, field); } } return fields; } - protected static void fillField(Map root, List fields, PropertyDescriptor propertyDescriptor, Field field) { - Class typeClass = propertyDescriptor.getPropertyType(); - Method readMethod = propertyDescriptor.getReadMethod(); + protected static void fillField(Map root, List fields, java.lang.reflect.Field f, Field field) { + Class typeClass = f.getType(); BasicField value; if (field.type() == DataType.OBJ || field.type() == DataType.LIST) { if (Collection.class.isAssignableFrom(typeClass)) - typeClass = (Class) ((ParameterizedType) readMethod.getGenericReturnType()).getActualTypeArguments()[0]; + typeClass = (Class) ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0]; loadSchema(root, typeClass); Schema schema = root.get(typeClass.getName()); - value = FieldFactory.create(field, propertyDescriptor, schema); + value = FieldFactory.create(field, f, schema); fields.add(value); } else { - value = FieldFactory.create(field, propertyDescriptor); + value = FieldFactory.create(field, f); fields.add(value); } } diff --git a/src/main/java/io/github/yezhihao/protostar/LoadStrategy.java b/src/main/java/io/github/yezhihao/protostar/LoadStrategy.java index c116212..d5d499a 100644 --- a/src/main/java/io/github/yezhihao/protostar/LoadStrategy.java +++ b/src/main/java/io/github/yezhihao/protostar/LoadStrategy.java @@ -5,55 +5,50 @@ import io.github.yezhihao.protostar.annotation.Fs; import io.github.yezhihao.protostar.field.BasicField; import io.github.yezhihao.protostar.schema.RuntimeSchema; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.util.*; /** - * Schema加载策略 + * RuntimeSchema加载策略 * @author yezhihao * home https://gitee.com/yezhihao/jt808-server */ public abstract class LoadStrategy { - protected Map>> typeIdMapping = new HashMap<>(64); + protected Map>> typeIdMapping = new HashMap<>(64); - public abstract Map> getSchema(Class typeClass); + public abstract Map> getRuntimeSchema(Class typeClass); - public abstract Schema getSchema(Class typeClass, Integer version); + public abstract RuntimeSchema getRuntimeSchema(Class typeClass, Integer version); - public Schema getSchema(Object typeId, Integer version) { - Map> schemaMap = typeIdMapping.get(typeId); + public RuntimeSchema getRuntimeSchema(Object typeId, Integer version) { + Map> schemaMap = typeIdMapping.get(typeId); if (schemaMap == null) return null; return schemaMap.get(version); } - protected void loadSchema(Map>> root, Object typeId, Class typeClass) { - Map> schemas = typeIdMapping.get(typeId); + protected void loadRuntimeSchema(Map>> root, Object typeId, Class typeClass) { + Map> schemas = typeIdMapping.get(typeId); if (schemas == null) { - schemas = loadSchema(root, typeClass); + schemas = loadRuntimeSchema(root, typeClass); typeIdMapping.put(typeId, schemas); } } - protected Map> loadSchema(Map>> root, Class typeClass) { - Map> schemas = root.get(typeClass.getName()); + protected Map> loadRuntimeSchema(Map>> root, Class typeClass) { + Map> schemas = root.get(typeClass.getName()); //不支持循环引用 if (schemas != null) return schemas; - List properties = findFieldProperties(typeClass); - if (properties.isEmpty()) + List fs = findFields(typeClass); + if (fs.isEmpty()) return null; root.put(typeClass.getName(), schemas = new HashMap(4)); - Map> multiVersionFields = findMultiVersionFields(root, properties); + Map> multiVersionFields = findMultiVersionFields(root, fs); for (Map.Entry> entry : multiVersionFields.entrySet()) { Integer version = entry.getKey(); @@ -62,79 +57,68 @@ public abstract class LoadStrategy { BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]); Arrays.sort(fields); - Schema schema = new RuntimeSchema(typeClass, version, fields); + RuntimeSchema schema = new RuntimeSchema(typeClass, version, fields); schemas.put(version, schema); } return schemas; } - protected List findFieldProperties(Class typeClass) { - BeanInfo beanInfo; - try { - beanInfo = Introspector.getBeanInfo(typeClass); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors(); - List result = new ArrayList<>(properties.length); + protected List findFields(Class typeClass) { + java.lang.reflect.Field[] fs = typeClass.getDeclaredFields(); - for (PropertyDescriptor property : properties) { - Method readMethod = property.getReadMethod(); + List result = new ArrayList<>(fs.length); - if (readMethod != null) { - if (readMethod.isAnnotationPresent(Fs.class) || readMethod.isAnnotationPresent(Field.class)) { - result.add(property); - } + for (java.lang.reflect.Field f : fs) { + if (f.isAnnotationPresent(Fs.class) || f.isAnnotationPresent(Field.class)) { + result.add(f); } } return result; } - protected Map> findMultiVersionFields(Map>> root, List properties) { + protected Map> findMultiVersionFields(Map>> root, List fs) { Map> multiVersionFields = new TreeMap>() { @Override public List get(Object key) { List result = super.get(key); if (result == null) - super.put((Integer) key, result = new ArrayList<>(properties.size())); + super.put((Integer) key, result = new ArrayList<>(fs.size())); return result; } }; - for (PropertyDescriptor property : properties) { - Method readMethod = property.getReadMethod(); + for (java.lang.reflect.Field f : fs) { - Field field = readMethod.getDeclaredAnnotation(Field.class); + Field field = f.getDeclaredAnnotation(Field.class); if (field != null) { - fillField(root, multiVersionFields, property, field); + fillField(root, multiVersionFields, f, field); } else { - Field[] fields = readMethod.getDeclaredAnnotation(Fs.class).value(); + Field[] fields = f.getDeclaredAnnotation(Fs.class).value(); for (int i = 0; i < fields.length; i++) - fillField(root, multiVersionFields, property, fields[i]); + fillField(root, multiVersionFields, f, fields[i]); } } return multiVersionFields; } - protected void fillField(Map>> root, Map> multiVersionFields, PropertyDescriptor propertyDescriptor, Field field) { - Class typeClass = propertyDescriptor.getPropertyType(); - Method readMethod = propertyDescriptor.getReadMethod(); + protected void fillField(Map>> root, Map> multiVersionFields, java.lang.reflect.Field f, Field field) { + Class typeClass = f.getType(); BasicField value; int[] versions = field.version(); if (field.type() == DataType.OBJ || field.type() == DataType.LIST) { if (Collection.class.isAssignableFrom(typeClass)) - typeClass = (Class) ((ParameterizedType) readMethod.getGenericReturnType()).getActualTypeArguments()[0]; - loadSchema(root, typeClass); + typeClass = (Class) ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0]; + loadRuntimeSchema(root, typeClass); for (int ver : versions) { - Map> schemaMap = root.getOrDefault(typeClass.getName(), Collections.EMPTY_MAP); - Schema schema = schemaMap.get(ver); - value = FieldFactory.create(field, propertyDescriptor, schema); + Map> schemaMap = root.getOrDefault(typeClass.getName(), Collections.EMPTY_MAP); + RuntimeSchema schema = schemaMap.get(ver); + value = FieldFactory.create(field, f, schema); multiVersionFields.get(ver).add(value); } } else { - value = FieldFactory.create(field, propertyDescriptor); + value = FieldFactory.create(field, f); for (int ver : versions) { multiVersionFields.get(ver).add(value); } diff --git a/src/main/java/io/github/yezhihao/protostar/ProtostarUtil.java b/src/main/java/io/github/yezhihao/protostar/ProtostarUtil.java index 9000d4e..7832489 100644 --- a/src/main/java/io/github/yezhihao/protostar/ProtostarUtil.java +++ b/src/main/java/io/github/yezhihao/protostar/ProtostarUtil.java @@ -1,5 +1,7 @@ package io.github.yezhihao.protostar; +import io.github.yezhihao.protostar.schema.RuntimeSchema; + import java.util.Map; /** @@ -24,15 +26,15 @@ public class ProtostarUtil { } } - public static Schema getSchema(Object typeId, Integer version) { - return LOAD_STRATEGY.getSchema(typeId, version); + public static RuntimeSchema getRuntimeSchema(Object typeId, Integer version) { + return LOAD_STRATEGY.getRuntimeSchema(typeId, version); } - public static Schema getSchema(Class typeClass, Integer version) { - return LOAD_STRATEGY.getSchema(typeClass, version); + public static RuntimeSchema getRuntimeSchema(Class typeClass, Integer version) { + return LOAD_STRATEGY.getRuntimeSchema(typeClass, version); } - public static Map> getSchema(Class typeClass) { - return LOAD_STRATEGY.getSchema(typeClass); + public static Map> getRuntimeSchema(Class typeClass) { + return LOAD_STRATEGY.getRuntimeSchema(typeClass); } } \ No newline at end of file diff --git a/src/main/java/io/github/yezhihao/protostar/annotation/Convert.java b/src/main/java/io/github/yezhihao/protostar/annotation/Convert.java index bb6ea32..3f93d04 100644 --- a/src/main/java/io/github/yezhihao/protostar/annotation/Convert.java +++ b/src/main/java/io/github/yezhihao/protostar/annotation/Convert.java @@ -12,7 +12,7 @@ import java.lang.annotation.Target; * @author yezhihao * home https://gitee.com/yezhihao/jt808-server */ -@Target(ElementType.METHOD) +@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Convert { diff --git a/src/main/java/io/github/yezhihao/protostar/annotation/Field.java b/src/main/java/io/github/yezhihao/protostar/annotation/Field.java index 67db46d..22281d5 100644 --- a/src/main/java/io/github/yezhihao/protostar/annotation/Field.java +++ b/src/main/java/io/github/yezhihao/protostar/annotation/Field.java @@ -9,7 +9,7 @@ import java.lang.annotation.*; * home https://gitee.com/yezhihao/jt808-server */ @Repeatable(Fs.class) -@Target(ElementType.METHOD) +@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Field { diff --git a/src/main/java/io/github/yezhihao/protostar/annotation/Fs.java b/src/main/java/io/github/yezhihao/protostar/annotation/Fs.java index 6444b47..63eaf72 100644 --- a/src/main/java/io/github/yezhihao/protostar/annotation/Fs.java +++ b/src/main/java/io/github/yezhihao/protostar/annotation/Fs.java @@ -9,7 +9,7 @@ import java.lang.annotation.Target; * @author yezhihao * home https://gitee.com/yezhihao/jt808-server */ -@Target(ElementType.METHOD) +@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Fs { diff --git a/src/main/java/io/github/yezhihao/protostar/field/BasicField.java b/src/main/java/io/github/yezhihao/protostar/field/BasicField.java index 4fd677a..99ae93d 100644 --- a/src/main/java/io/github/yezhihao/protostar/field/BasicField.java +++ b/src/main/java/io/github/yezhihao/protostar/field/BasicField.java @@ -6,9 +6,6 @@ import io.netty.buffer.ByteBuf; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; - /** * 固定长度的字段 * @author yezhihao @@ -19,23 +16,21 @@ public abstract class BasicField implements Comparable> { protected final int index; protected final int length; - protected final String desc; - protected final Method readMethod; - protected final Method writeMethod; - protected final PropertyDescriptor property; protected final Field field; + protected final java.lang.reflect.Field f; - public BasicField(Field field, PropertyDescriptor property) { + public BasicField(Field field, java.lang.reflect.Field f) { this.index = field.index(); int length = field.length(); if (length < 0) length = field.type().length; this.length = length; - this.desc = field.desc(); - this.readMethod = property.getReadMethod(); - this.writeMethod = property.getWriteMethod(); this.field = field; - this.property = property; + this.f = f; + try { + f.setAccessible(true); + } catch (Exception e) { + } } public abstract boolean readFrom(ByteBuf input, Object message) throws Exception; @@ -62,13 +57,12 @@ public abstract class BasicField implements Comparable> { @Override public String toString() { - final StringBuilder sb = new StringBuilder(60); + final StringBuilder sb = new StringBuilder(50); sb.append('{'); sb.append("index=").append(index); sb.append(", length=").append(length); - sb.append(", desc").append(desc); - sb.append(", readMethod=").append(readMethod.getName()); - sb.append(", writeMethod=").append(writeMethod.getName()); + sb.append(", desc").append(field.desc()); + sb.append(", field=").append(f.getName()); sb.append('}'); return sb.toString(); } diff --git a/src/main/java/io/github/yezhihao/protostar/field/DynamicLengthField.java b/src/main/java/io/github/yezhihao/protostar/field/DynamicLengthField.java index db7ca8a..998b629 100644 --- a/src/main/java/io/github/yezhihao/protostar/field/DynamicLengthField.java +++ b/src/main/java/io/github/yezhihao/protostar/field/DynamicLengthField.java @@ -1,12 +1,10 @@ package io.github.yezhihao.protostar.field; +import io.github.yezhihao.protostar.Schema; import io.github.yezhihao.protostar.annotation.Field; +import io.github.yezhihao.protostar.util.ByteBufUtils; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import io.github.yezhihao.protostar.Schema; -import io.github.yezhihao.protostar.util.ByteBufUtils; - -import java.beans.PropertyDescriptor; /** * 动态长度的字段 @@ -19,8 +17,8 @@ public class DynamicLengthField extends BasicField { protected final int lengthSize; - public DynamicLengthField(Field field, PropertyDescriptor property, Schema schema) { - super(field, property); + public DynamicLengthField(Field field, java.lang.reflect.Field f, Schema schema) { + super(field, f); this.schema = schema; this.lengthSize = field.lengthSize(); } @@ -30,12 +28,12 @@ public class DynamicLengthField extends BasicField { if (!input.isReadable(length)) return false; Object value = schema.readFrom(input, length); - writeMethod.invoke(message, value); + f.set(message, value); return true; } public void writeTo(ByteBuf output, Object message) throws Exception { - Object value = readMethod.invoke(message); + Object value = f.get(message); if (value != null) { int begin = output.writerIndex(); output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]); @@ -55,8 +53,8 @@ public class DynamicLengthField extends BasicField { public static class Logger extends DynamicLengthField { - public Logger(Field field, PropertyDescriptor property, Schema schema) { - super(field, property, schema); + public Logger(Field field, java.lang.reflect.Field f, Schema schema) { + super(field, f, schema); } public boolean readFrom(ByteBuf input, Object message) throws Exception { @@ -66,18 +64,18 @@ public class DynamicLengthField extends BasicField { if (!input.isReadable(length)) return false; Object value = schema.readFrom(input, length); - writeMethod.invoke(message, value); + f.set(message, value); int after = input.readerIndex(); String hex = ByteBufUtil.hexDump(input.slice(before, after - before)); - println(this.index, this.desc, hex, value); + println(this.index, this.field.desc(), hex, value); return true; } public void writeTo(ByteBuf output, Object message) throws Exception { int before = output.writerIndex(); - Object value = readMethod.invoke(message); + Object value = f.get(message); if (value != null) { int begin = output.writerIndex(); output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]); @@ -88,7 +86,7 @@ public class DynamicLengthField extends BasicField { int after = output.writerIndex(); String hex = ByteBufUtil.hexDump(output.slice(before, after - before)); - println(this.index, this.desc, hex, value); + println(this.index, this.field.desc(), hex, value); } } } \ No newline at end of file diff --git a/src/main/java/io/github/yezhihao/protostar/field/FixedField.java b/src/main/java/io/github/yezhihao/protostar/field/FixedField.java index 7921c79..cc21653 100644 --- a/src/main/java/io/github/yezhihao/protostar/field/FixedField.java +++ b/src/main/java/io/github/yezhihao/protostar/field/FixedField.java @@ -1,11 +1,9 @@ package io.github.yezhihao.protostar.field; +import io.github.yezhihao.protostar.Schema; import io.github.yezhihao.protostar.annotation.Field; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import io.github.yezhihao.protostar.Schema; - -import java.beans.PropertyDescriptor; /** * 原子域 @@ -16,51 +14,51 @@ public class FixedField extends BasicField { protected final Schema schema; - public FixedField(Field field, PropertyDescriptor property, Schema schema) { - super(field, property); + public FixedField(Field field, java.lang.reflect.Field f, Schema schema) { + super(field, f); this.schema = schema; } public boolean readFrom(ByteBuf input, Object message) throws Exception { Object value = schema.readFrom(input); - writeMethod.invoke(message, value); + f.set(message, value); return true; } public void writeTo(ByteBuf output, Object message) throws Exception { - Object value = readMethod.invoke(message); + Object value = f.get(message); if (value != null) schema.writeTo(output, (T) value); } public static class Logger extends FixedField { - public Logger(Field field, PropertyDescriptor property, Schema schema) { - super(field, property, schema); + public Logger(Field field, java.lang.reflect.Field f, Schema schema) { + super(field, f, schema); } public boolean readFrom(ByteBuf input, Object message) throws Exception { int before = input.readerIndex(); Object value = schema.readFrom(input); - writeMethod.invoke(message, value); + f.set(message, value); int after = input.readerIndex(); String hex = ByteBufUtil.hexDump(input.slice(before, after - before)); - println(this.index, this.desc, hex, value); + println(this.index, this.field.desc(), hex, value); return true; } public void writeTo(ByteBuf output, Object message) throws Exception { int before = output.writerIndex(); - Object value = readMethod.invoke(message); + Object value = f.get(message); if (value != null) schema.writeTo(output, (T) value); int after = output.writerIndex(); String hex = ByteBufUtil.hexDump(output.slice(before, after - before)); - println(this.index, this.desc, hex, value); + println(this.index, this.field.desc(), hex, value); } } } \ No newline at end of file diff --git a/src/main/java/io/github/yezhihao/protostar/field/FixedLengthField.java b/src/main/java/io/github/yezhihao/protostar/field/FixedLengthField.java index 569849e..17fe6d5 100644 --- a/src/main/java/io/github/yezhihao/protostar/field/FixedLengthField.java +++ b/src/main/java/io/github/yezhihao/protostar/field/FixedLengthField.java @@ -1,11 +1,9 @@ package io.github.yezhihao.protostar.field; +import io.github.yezhihao.protostar.Schema; import io.github.yezhihao.protostar.annotation.Field; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import io.github.yezhihao.protostar.Schema; - -import java.beans.PropertyDescriptor; /** * 固定长度的字段 @@ -16,51 +14,51 @@ public class FixedLengthField extends BasicField { protected final Schema schema; - public FixedLengthField(Field field, PropertyDescriptor property, Schema schema) { - super(field, property); + public FixedLengthField(Field field, java.lang.reflect.Field f, Schema schema) { + super(field, f); this.schema = schema; } public boolean readFrom(ByteBuf input, Object message) throws Exception { Object value = schema.readFrom(input, length); - writeMethod.invoke(message, value); + f.set(message, value); return true; } public void writeTo(ByteBuf output, Object message) throws Exception { - Object value = readMethod.invoke(message); + Object value = f.get(message); if (value != null) schema.writeTo(output, length, (T) value); } public static class Logger extends FixedLengthField { - public Logger(Field field, PropertyDescriptor property, Schema schema) { - super(field, property, schema); + public Logger(Field field, java.lang.reflect.Field f, Schema schema) { + super(field, f, schema); } public boolean readFrom(ByteBuf input, Object message) throws Exception { int before = input.readerIndex(); Object value = schema.readFrom(input, length); - writeMethod.invoke(message, value); + f.set(message, value); int after = input.readerIndex(); String hex = ByteBufUtil.hexDump(input.slice(before, after - before)); - println(this.index, this.desc, hex, value); + println(this.index, this.field.desc(), hex, value); return true; } public void writeTo(ByteBuf output, Object message) throws Exception { int before = output.writerIndex(); - Object value = readMethod.invoke(message); + Object value = f.get(message); if (value != null) schema.writeTo(output, length, (T) value); int after = output.writerIndex(); String hex = ByteBufUtil.hexDump(output.slice(before, after - before)); - println(this.index, this.desc, hex, value); + println(this.index, this.field.desc(), hex, value); } } } \ No newline at end of file diff --git a/src/main/java/io/github/yezhihao/protostar/schema/RuntimeSchema.java b/src/main/java/io/github/yezhihao/protostar/schema/RuntimeSchema.java index 09091f9..2017a37 100644 --- a/src/main/java/io/github/yezhihao/protostar/schema/RuntimeSchema.java +++ b/src/main/java/io/github/yezhihao/protostar/schema/RuntimeSchema.java @@ -34,6 +34,29 @@ public class RuntimeSchema implements Schema { } } + public T newInstance() { + try { + return constructor.newInstance((Object[]) null); + } catch (Exception e) { + throw new RuntimeException("newInstance failed " + typeClass.getName(), e); + } + } + + public T mergeFrom(ByteBuf input, T result) { + BasicField field = null; + try { + for (int i = 0; i < fields.length; i++) { + if (!input.isReadable()) + break; + field = fields[i]; + field.readFrom(input, result); + } + return result; + } catch (Exception e) { + throw new RuntimeException("Read failed " + typeClass.getName() + field, e); + } + } + public T readFrom(ByteBuf input) { BasicField field = null; try { diff --git a/src/test/java/io/github/yezhihao/protostar/convert/Attr1.java b/src/test/java/io/github/yezhihao/protostar/convert/Attr1.java index c719a1a..d65fa64 100644 --- a/src/test/java/io/github/yezhihao/protostar/convert/Attr1.java +++ b/src/test/java/io/github/yezhihao/protostar/convert/Attr1.java @@ -5,7 +5,9 @@ import io.github.yezhihao.protostar.annotation.Field; public class Attr1 { + @Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称") private String name; + @Field(index = 1, type = DataType.WORD, desc = "ID") private int id; public Attr1() { @@ -16,7 +18,6 @@ public class Attr1 { this.id = id; } - @Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称") public String getName() { return name; } @@ -25,7 +26,6 @@ public class Attr1 { this.name = name; } - @Field(index = 1, type = DataType.WORD, desc = "ID") public int getId() { return id; } diff --git a/src/test/java/io/github/yezhihao/protostar/convert/Test.java b/src/test/java/io/github/yezhihao/protostar/convert/Test.java index d68e1ad..15ba5f8 100644 --- a/src/test/java/io/github/yezhihao/protostar/convert/Test.java +++ b/src/test/java/io/github/yezhihao/protostar/convert/Test.java @@ -2,10 +2,9 @@ package io.github.yezhihao.protostar.convert; import io.github.yezhihao.protostar.DataType; import io.github.yezhihao.protostar.ProtostarUtil; -import io.github.yezhihao.protostar.Schema; import io.github.yezhihao.protostar.annotation.Convert; import io.github.yezhihao.protostar.annotation.Field; -import io.github.yezhihao.protostar.annotation.Fs; +import io.github.yezhihao.protostar.schema.RuntimeSchema; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; @@ -17,9 +16,9 @@ import java.util.TreeMap; public class Test { public static void main(String[] args) { - Map> multiVersionSchema = ProtostarUtil.getSchema(Foo.class); - Schema schema_v0 = multiVersionSchema.get(0); - Schema schema_v1 = multiVersionSchema.get(1); + Map> multiVersionSchema = ProtostarUtil.getRuntimeSchema(Foo.class); + RuntimeSchema schema_v0 = multiVersionSchema.get(0); + RuntimeSchema schema_v1 = multiVersionSchema.get(1); ByteBuf buffer = Unpooled.buffer(32); schema_v0.writeTo(buffer, foo()); @@ -56,13 +55,18 @@ public class Test { public static class Foo { + @Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称", version = 0) + @Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1) private String name; + @Field(index = 1, type = DataType.WORD, desc = "ID", version = 0) + @Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1) private int id; + @Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1}) private LocalDateTime dateTime; + @Convert(converter = AttributeConverter.class) + @Field(index = 4, type = DataType.MAP, desc = "属性", version = {0, 1}) private Map attributes; - @Fs({@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称", version = 0), - @Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1)}) public String getName() { return name; } @@ -71,8 +75,6 @@ public class Test { this.name = name; } - @Fs({@Field(index = 1, type = DataType.WORD, desc = "ID", version = 0), - @Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1)}) public int getId() { return id; } @@ -81,7 +83,6 @@ public class Test { this.id = id; } - @Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1}) public LocalDateTime getDateTime() { return dateTime; } @@ -90,8 +91,6 @@ public class Test { this.dateTime = dateTime; } - @Convert(converter = AttributeConverter.class) - @Field(index = 4, type = DataType.MAP, desc = "属性", version = {0, 1}) public Map getAttributes() { return attributes; } diff --git a/src/test/java/io/github/yezhihao/protostar/multiversion/Test.java b/src/test/java/io/github/yezhihao/protostar/multiversion/Test.java index c345b47..d2d36d2 100644 --- a/src/test/java/io/github/yezhihao/protostar/multiversion/Test.java +++ b/src/test/java/io/github/yezhihao/protostar/multiversion/Test.java @@ -2,8 +2,8 @@ package io.github.yezhihao.protostar.multiversion; import io.github.yezhihao.protostar.DataType; import io.github.yezhihao.protostar.ProtostarUtil; -import io.github.yezhihao.protostar.Schema; import io.github.yezhihao.protostar.annotation.Field; +import io.github.yezhihao.protostar.schema.RuntimeSchema; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; @@ -14,9 +14,9 @@ import java.util.Map; public class Test { public static void main(String[] args) { - Map> multiVersionSchema = ProtostarUtil.getSchema(Foo.class); - Schema schema_v0 = multiVersionSchema.get(0); - Schema schema_v1 = multiVersionSchema.get(1); + Map> multiVersionSchema = ProtostarUtil.getRuntimeSchema(Foo.class); + RuntimeSchema schema_v0 = multiVersionSchema.get(0); + RuntimeSchema schema_v1 = multiVersionSchema.get(1); ByteBuf buffer = Unpooled.buffer(32); Foo foo = foo(); @@ -48,12 +48,15 @@ public class Test { public static class Foo { - private String name; - private int id; - private LocalDateTime dateTime; - @Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称", version = 0) @Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1) + private String name; + @Field(index = 1, type = DataType.WORD, desc = "ID", version = 0) + @Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1) + private int id; + @Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1}) + private LocalDateTime dateTime; + public String getName() { return name; } @@ -62,8 +65,6 @@ public class Test { this.name = name; } - @Field(index = 1, type = DataType.WORD, desc = "ID", version = 0) - @Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1) public int getId() { return id; } @@ -72,7 +73,6 @@ public class Test { this.id = id; } - @Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1}) public LocalDateTime getDateTime() { return dateTime; } diff --git a/src/test/java/io/github/yezhihao/protostar/simple/Test.java b/src/test/java/io/github/yezhihao/protostar/simple/Test.java index ba2271a..f9bec45 100644 --- a/src/test/java/io/github/yezhihao/protostar/simple/Test.java +++ b/src/test/java/io/github/yezhihao/protostar/simple/Test.java @@ -3,8 +3,8 @@ package io.github.yezhihao.protostar.simple; import io.github.yezhihao.protostar.DataType; import io.github.yezhihao.protostar.FieldFactory; import io.github.yezhihao.protostar.ProtostarUtil; -import io.github.yezhihao.protostar.Schema; import io.github.yezhihao.protostar.annotation.Field; +import io.github.yezhihao.protostar.schema.RuntimeSchema; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; @@ -17,16 +17,24 @@ public class Test { public static void main(String[] args) { FieldFactory.EXPLAIN = true; - Map> multiVersionSchema = ProtostarUtil.getSchema(Foo.class); - Schema schema = multiVersionSchema.get(0); + Map> bodySchemas = ProtostarUtil.getRuntimeSchema(Foo.class); + RuntimeSchema bodySchema = bodySchemas.get(0); + + Map> headSchemas = ProtostarUtil.getRuntimeSchema(BaseDO.class); + RuntimeSchema headSchema = headSchemas.get(0); ByteBuf buffer = Unpooled.buffer(32); Foo foo = foo(); - schema.writeTo(buffer, foo); + headSchema.writeTo(buffer, foo); + bodySchema.writeTo(buffer, foo); + String hex = ByteBufUtil.hexDump(buffer); System.out.println(hex); - foo = schema.readFrom(buffer); + + Foo foo1 = new Foo(); + headSchema.mergeFrom(buffer, foo1); + bodySchema.mergeFrom(buffer, foo1); System.out.println(foo); } @@ -35,16 +43,45 @@ public class Test { foo.setName("张三"); foo.setId(128); foo.setDateTime(LocalDateTime.of(2020, 7, 7, 19, 23, 59)); + + foo.setType(1); + foo.setClientId("123qwe"); return foo; } - public static class Foo { + public static class BaseDO { - private String name; - private int id; - private LocalDateTime dateTime; + @Field(index = 0, type = DataType.WORD, desc = "ID") + protected int type; + @Field(index = 1, type = DataType.STRING, length = 20, desc = "名称") + protected String clientId; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + } + + public static class Foo extends BaseDO { @Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称") + private String name; + @Field(index = 1, type = DataType.WORD, desc = "ID") + private int id; + @Field(index = 3, type = DataType.BCD8421, desc = "日期") + private LocalDateTime dateTime; + public String getName() { return name; } @@ -53,7 +90,6 @@ public class Test { this.name = name; } - @Field(index = 1, type = DataType.WORD, desc = "ID") public int getId() { return id; } @@ -62,7 +98,6 @@ public class Test { this.id = id; } - @Field(index = 3, type = DataType.BCD8421, desc = "日期") public LocalDateTime getDateTime() { return dateTime; } @@ -74,7 +109,9 @@ public class Test { @Override public String toString() { final StringBuilder sb = new StringBuilder("Foo{"); - sb.append("name='").append(name).append('\''); + sb.append("type=").append(type); + sb.append(", clientId='").append(clientId).append('\''); + sb.append(", name='").append(name).append('\''); sb.append(", id=").append(id); sb.append(", dateTime=").append(dateTime); sb.append('}');