deployed 2.0.0.RELEASE,升级相关依赖

使用RuntimeSchema
使用反射(Field)取代内省(PropertyDescriptor),以兼容android平台
master
剑器近 2021-06-25 16:12:20 +08:00
parent a6e0e7c819
commit c305df04b9
18 changed files with 234 additions and 221 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>io.github.yezhihao</groupId> <groupId>io.github.yezhihao</groupId>
<artifactId>protostar</artifactId> <artifactId>protostar</artifactId>
<version>1.0.5.RELEASE</version> <version>2.0.0.RELEASE</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Protostar</name> <name>Protostar</name>
@ -50,13 +50,13 @@
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>slf4j-simple</artifactId>
<version>1.7.30</version> <version>1.7.31</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<version>1.7.30</version> <version>1.7.31</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -1,9 +1,9 @@
package io.github.yezhihao.protostar; package io.github.yezhihao.protostar;
import io.github.yezhihao.protostar.annotation.Message; import io.github.yezhihao.protostar.annotation.Message;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.github.yezhihao.protostar.util.ClassUtils; import io.github.yezhihao.protostar.util.ClassUtils;
import java.beans.Introspector;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -14,7 +14,7 @@ import java.util.Map;
*/ */
public class DefaultLoadStrategy extends LoadStrategy { public class DefaultLoadStrategy extends LoadStrategy {
private Map<String, Map<Integer, Schema<?>>> typeClassMapping = new HashMap(140); private Map<String, Map<Integer, RuntimeSchema<?>>> typeClassMapping = new HashMap(140);
public DefaultLoadStrategy() { public DefaultLoadStrategy() {
} }
@ -26,33 +26,32 @@ public class DefaultLoadStrategy extends LoadStrategy {
if (message != null) { if (message != null) {
int[] values = message.value(); int[] values = message.value();
for (int typeId : values) for (int typeId : values)
loadSchema(typeClassMapping, typeId, type); loadRuntimeSchema(typeClassMapping, typeId, type);
} }
} }
Introspector.flushCaches();
} }
@Override @Override
public <T> Schema<T> getSchema(Class<T> typeClass, Integer version) { public <T> RuntimeSchema<T> getRuntimeSchema(Class<T> typeClass, Integer version) {
Map<Integer, Schema<?>> schemas = typeClassMapping.get(typeClass.getName()); Map<Integer, RuntimeSchema<?>> schemas = typeClassMapping.get(typeClass.getName());
if (schemas == null) { if (schemas == null) {
schemas = loadSchema(typeClassMapping, typeClass); schemas = loadRuntimeSchema(typeClassMapping, typeClass);
} }
if (schemas == null) return null; if (schemas == null) return null;
return (Schema<T>) schemas.get(version); return (RuntimeSchema<T>) schemas.get(version);
} }
@Override @Override
public <T> Map<Integer, Schema<T>> getSchema(Class<T> typeClass) { public <T> Map<Integer, RuntimeSchema<T>> getRuntimeSchema(Class<T> typeClass) {
Map<Integer, Schema<?>> schemas = typeClassMapping.get(typeClass.getName()); Map<Integer, RuntimeSchema<?>> schemas = typeClassMapping.get(typeClass.getName());
if (schemas == null) { if (schemas == null) {
schemas = loadSchema(typeClassMapping, typeClass); schemas = loadRuntimeSchema(typeClassMapping, typeClass);
} }
if (schemas == null) return null; if (schemas == null) return null;
HashMap<Integer, Schema<T>> result = new HashMap<>(schemas.size()); HashMap<Integer, RuntimeSchema<T>> result = new HashMap<>(schemas.size());
for (Map.Entry<Integer, Schema<?>> entry : schemas.entrySet()) { for (Map.Entry<Integer, RuntimeSchema<?>> entry : schemas.entrySet()) {
result.put(entry.getKey(), (Schema<T>) entry.getValue()); result.put(entry.getKey(), (RuntimeSchema<T>) entry.getValue());
} }
return result; return result;
} }

View File

@ -10,7 +10,6 @@ import io.github.yezhihao.protostar.schema.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.beans.PropertyDescriptor;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -23,13 +22,13 @@ public abstract class FieldFactory {
protected static Logger log = LoggerFactory.getLogger(FieldFactory.class.getSimpleName()); protected static Logger log = LoggerFactory.getLogger(FieldFactory.class.getSimpleName());
public static boolean EXPLAIN = false; public static boolean EXPLAIN = false;
public static BasicField create(Field field, PropertyDescriptor property) { public static BasicField create(Field field, java.lang.reflect.Field f) {
return create(field, property, null); 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(); DataType dataType = field.type();
Class<?> typeClass = property.getPropertyType(); Class<?> typeClass = f.getType();
Schema fieldSchema; Schema fieldSchema;
switch (dataType) { switch (dataType) {
@ -63,7 +62,7 @@ public abstract class FieldFactory {
if (schema != null) { if (schema != null) {
fieldSchema = ObjectSchema.getInstance(schema); fieldSchema = ObjectSchema.getInstance(schema);
} else { } else {
Convert convert = property.getReadMethod().getAnnotation(Convert.class); Convert convert = f.getAnnotation(Convert.class);
fieldSchema = ConvertSchema.getInstance(convert.converter()); fieldSchema = ConvertSchema.getInstance(convert.converter());
} }
break; break;
@ -71,7 +70,7 @@ public abstract class FieldFactory {
fieldSchema = CollectionSchema.getInstance(schema); fieldSchema = CollectionSchema.getInstance(schema);
break; break;
case MAP: case MAP:
Convert convert = property.getReadMethod().getAnnotation(Convert.class); Convert convert = f.getAnnotation(Convert.class);
fieldSchema = ConvertSchema.getInstance(convert.converter()); fieldSchema = ConvertSchema.getInstance(convert.converter());
break; break;
default: default:
@ -82,19 +81,19 @@ public abstract class FieldFactory {
BasicField result; BasicField result;
if (EXPLAIN) { if (EXPLAIN) {
if (field.lengthSize() > 0) { if (field.lengthSize() > 0) {
result = new DynamicLengthField.Logger(field, property, fieldSchema); result = new DynamicLengthField.Logger(field, f, fieldSchema);
} else if (field.length() > 0) { } else if (field.length() > 0) {
result = new FixedLengthField.Logger(field, property, fieldSchema); result = new FixedLengthField.Logger(field, f, fieldSchema);
} else { } else {
result = new FixedField.Logger(field, property, fieldSchema); result = new FixedField.Logger(field, f, fieldSchema);
} }
} else { } else {
if (field.lengthSize() > 0) { if (field.lengthSize() > 0) {
result = new DynamicLengthField(field, property, fieldSchema); result = new DynamicLengthField(field, f, fieldSchema);
} else if (field.length() > 0) { } else if (field.length() > 0) {
result = new FixedLengthField(field, property, fieldSchema); result = new FixedLengthField(field, f, fieldSchema);
} else { } else {
result = new FixedField(field, property, fieldSchema); result = new FixedField(field, f, fieldSchema);
} }
} }
return result; return result;

View File

@ -5,11 +5,6 @@ import io.github.yezhihao.protostar.field.BasicField;
import io.github.yezhihao.protostar.schema.RuntimeSchema; import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.netty.buffer.ByteBuf; 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.lang.reflect.ParameterizedType;
import java.util.*; import java.util.*;
@ -54,11 +49,11 @@ public abstract class IdStrategy {
if (schema != null) if (schema != null)
return (Schema<T>) schema; return (Schema<T>) schema;
List<PropertyDescriptor> properties = findFieldProperties(typeClass); List<java.lang.reflect.Field> fs = findFields(typeClass);
if (properties.isEmpty()) if (fs.isEmpty())
return null; return null;
List<BasicField> fieldList = findFields(root, properties); List<BasicField> fieldList = findFields(root, fs);
BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]); BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]);
Arrays.sort(fields); Arrays.sort(fields);
@ -67,57 +62,44 @@ public abstract class IdStrategy {
return (Schema<T>) schema; return (Schema<T>) schema;
} }
protected static List<PropertyDescriptor> findFieldProperties(Class typeClass) { protected static List<java.lang.reflect.Field> findFields(Class typeClass) {
BeanInfo beanInfo; java.lang.reflect.Field[] fields = typeClass.getDeclaredFields();
try { List<java.lang.reflect.Field> result = new ArrayList<>(fields.length);
beanInfo = Introspector.getBeanInfo(typeClass);
} catch (IntrospectionException e) {
throw new RuntimeException(e);
}
PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
List<PropertyDescriptor> result = new ArrayList<>(properties.length);
for (PropertyDescriptor property : properties) { for (java.lang.reflect.Field f : fields) {
Method readMethod = property.getReadMethod(); if (f.isAnnotationPresent(Field.class)) {
result.add(f);
if (readMethod != null) {
if (readMethod.isAnnotationPresent(Field.class)) {
result.add(property);
}
} }
} }
return result; return result;
} }
protected static List<BasicField> findFields(Map<Object, Schema> root, List<PropertyDescriptor> properties) { protected static List<BasicField> findFields(Map<Object, Schema> root, List<java.lang.reflect.Field> fs) {
List<BasicField> fields = new ArrayList<>(properties.size()); List<BasicField> fields = new ArrayList<>(fs.size());
for (PropertyDescriptor property : properties) { for (java.lang.reflect.Field f : fs) {
Method readMethod = property.getReadMethod(); Field field = f.getDeclaredAnnotation(Field.class);
Field field = readMethod.getDeclaredAnnotation(Field.class);
if (field != null) { if (field != null) {
fillField(root, fields, property, field); fillField(root, fields, f, field);
} }
} }
return fields; return fields;
} }
protected static void fillField(Map<Object, Schema> root, List<BasicField> fields, PropertyDescriptor propertyDescriptor, Field field) { protected static void fillField(Map<Object, Schema> root, List<BasicField> fields, java.lang.reflect.Field f, Field field) {
Class typeClass = propertyDescriptor.getPropertyType(); Class typeClass = f.getType();
Method readMethod = propertyDescriptor.getReadMethod();
BasicField value; BasicField value;
if (field.type() == DataType.OBJ || field.type() == DataType.LIST) { if (field.type() == DataType.OBJ || field.type() == DataType.LIST) {
if (Collection.class.isAssignableFrom(typeClass)) if (Collection.class.isAssignableFrom(typeClass))
typeClass = (Class) ((ParameterizedType) readMethod.getGenericReturnType()).getActualTypeArguments()[0]; typeClass = (Class) ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0];
loadSchema(root, typeClass); loadSchema(root, typeClass);
Schema schema = root.get(typeClass.getName()); Schema schema = root.get(typeClass.getName());
value = FieldFactory.create(field, propertyDescriptor, schema); value = FieldFactory.create(field, f, schema);
fields.add(value); fields.add(value);
} else { } else {
value = FieldFactory.create(field, propertyDescriptor); value = FieldFactory.create(field, f);
fields.add(value); fields.add(value);
} }
} }

View File

@ -5,55 +5,50 @@ import io.github.yezhihao.protostar.annotation.Fs;
import io.github.yezhihao.protostar.field.BasicField; import io.github.yezhihao.protostar.field.BasicField;
import io.github.yezhihao.protostar.schema.RuntimeSchema; 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.lang.reflect.ParameterizedType;
import java.util.*; import java.util.*;
/** /**
* Schema * RuntimeSchema
* @author yezhihao * @author yezhihao
* home https://gitee.com/yezhihao/jt808-server * home https://gitee.com/yezhihao/jt808-server
*/ */
public abstract class LoadStrategy { public abstract class LoadStrategy {
protected Map<Object, Map<Integer, Schema<?>>> typeIdMapping = new HashMap<>(64); protected Map<Object, Map<Integer, RuntimeSchema<?>>> typeIdMapping = new HashMap<>(64);
public abstract <T> Map<Integer, Schema<T>> getSchema(Class<T> typeClass); public abstract <T> Map<Integer, RuntimeSchema<T>> getRuntimeSchema(Class<T> typeClass);
public abstract <T> Schema<T> getSchema(Class<T> typeClass, Integer version); public abstract <T> RuntimeSchema<T> getRuntimeSchema(Class<T> typeClass, Integer version);
public Schema getSchema(Object typeId, Integer version) { public RuntimeSchema getRuntimeSchema(Object typeId, Integer version) {
Map<Integer, Schema<?>> schemaMap = typeIdMapping.get(typeId); Map<Integer, RuntimeSchema<?>> schemaMap = typeIdMapping.get(typeId);
if (schemaMap == null) if (schemaMap == null)
return null; return null;
return schemaMap.get(version); return schemaMap.get(version);
} }
protected void loadSchema(Map<String, Map<Integer, Schema<?>>> root, Object typeId, Class<?> typeClass) { protected void loadRuntimeSchema(Map<String, Map<Integer, RuntimeSchema<?>>> root, Object typeId, Class<?> typeClass) {
Map<Integer, Schema<?>> schemas = typeIdMapping.get(typeId); Map<Integer, RuntimeSchema<?>> schemas = typeIdMapping.get(typeId);
if (schemas == null) { if (schemas == null) {
schemas = loadSchema(root, typeClass); schemas = loadRuntimeSchema(root, typeClass);
typeIdMapping.put(typeId, schemas); typeIdMapping.put(typeId, schemas);
} }
} }
protected Map<Integer, Schema<?>> loadSchema(Map<String, Map<Integer, Schema<?>>> root, Class<?> typeClass) { protected Map<Integer, RuntimeSchema<?>> loadRuntimeSchema(Map<String, Map<Integer, RuntimeSchema<?>>> root, Class<?> typeClass) {
Map<Integer, Schema<?>> schemas = root.get(typeClass.getName()); Map<Integer, RuntimeSchema<?>> schemas = root.get(typeClass.getName());
//不支持循环引用 //不支持循环引用
if (schemas != null) if (schemas != null)
return schemas; return schemas;
List<PropertyDescriptor> properties = findFieldProperties(typeClass); List<java.lang.reflect.Field> fs = findFields(typeClass);
if (properties.isEmpty()) if (fs.isEmpty())
return null; return null;
root.put(typeClass.getName(), schemas = new HashMap(4)); root.put(typeClass.getName(), schemas = new HashMap(4));
Map<Integer, List<BasicField>> multiVersionFields = findMultiVersionFields(root, properties); Map<Integer, List<BasicField>> multiVersionFields = findMultiVersionFields(root, fs);
for (Map.Entry<Integer, List<BasicField>> entry : multiVersionFields.entrySet()) { for (Map.Entry<Integer, List<BasicField>> entry : multiVersionFields.entrySet()) {
Integer version = entry.getKey(); Integer version = entry.getKey();
@ -62,79 +57,68 @@ public abstract class LoadStrategy {
BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]); BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]);
Arrays.sort(fields); Arrays.sort(fields);
Schema schema = new RuntimeSchema(typeClass, version, fields); RuntimeSchema schema = new RuntimeSchema(typeClass, version, fields);
schemas.put(version, schema); schemas.put(version, schema);
} }
return schemas; return schemas;
} }
protected List<PropertyDescriptor> findFieldProperties(Class<?> typeClass) { protected List<java.lang.reflect.Field> findFields(Class<?> typeClass) {
BeanInfo beanInfo; java.lang.reflect.Field[] fs = typeClass.getDeclaredFields();
try {
beanInfo = Introspector.getBeanInfo(typeClass);
} catch (IntrospectionException e) {
throw new RuntimeException(e);
}
PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
List<PropertyDescriptor> result = new ArrayList<>(properties.length);
for (PropertyDescriptor property : properties) { List<java.lang.reflect.Field> result = new ArrayList<>(fs.length);
Method readMethod = property.getReadMethod();
if (readMethod != null) { for (java.lang.reflect.Field f : fs) {
if (readMethod.isAnnotationPresent(Fs.class) || readMethod.isAnnotationPresent(Field.class)) { if (f.isAnnotationPresent(Fs.class) || f.isAnnotationPresent(Field.class)) {
result.add(property); result.add(f);
}
} }
} }
return result; return result;
} }
protected Map<Integer, List<BasicField>> findMultiVersionFields(Map<String, Map<Integer, Schema<?>>> root, List<PropertyDescriptor> properties) { protected Map<Integer, List<BasicField>> findMultiVersionFields(Map<String, Map<Integer, RuntimeSchema<?>>> root, List<java.lang.reflect.Field> fs) {
Map<Integer, List<BasicField>> multiVersionFields = new TreeMap<Integer, List<BasicField>>() { Map<Integer, List<BasicField>> multiVersionFields = new TreeMap<Integer, List<BasicField>>() {
@Override @Override
public List<BasicField> get(Object key) { public List<BasicField> get(Object key) {
List result = super.get(key); List result = super.get(key);
if (result == null) if (result == null)
super.put((Integer) key, result = new ArrayList<>(properties.size())); super.put((Integer) key, result = new ArrayList<>(fs.size()));
return result; return result;
} }
}; };
for (PropertyDescriptor property : properties) { for (java.lang.reflect.Field f : fs) {
Method readMethod = property.getReadMethod();
Field field = readMethod.getDeclaredAnnotation(Field.class); Field field = f.getDeclaredAnnotation(Field.class);
if (field != null) { if (field != null) {
fillField(root, multiVersionFields, property, field); fillField(root, multiVersionFields, f, field);
} else { } else {
Field[] fields = readMethod.getDeclaredAnnotation(Fs.class).value(); Field[] fields = f.getDeclaredAnnotation(Fs.class).value();
for (int i = 0; i < fields.length; i++) for (int i = 0; i < fields.length; i++)
fillField(root, multiVersionFields, property, fields[i]); fillField(root, multiVersionFields, f, fields[i]);
} }
} }
return multiVersionFields; return multiVersionFields;
} }
protected void fillField(Map<String, Map<Integer, Schema<?>>> root, Map<Integer, List<BasicField>> multiVersionFields, PropertyDescriptor propertyDescriptor, Field field) { protected void fillField(Map<String, Map<Integer, RuntimeSchema<?>>> root, Map<Integer, List<BasicField>> multiVersionFields, java.lang.reflect.Field f, Field field) {
Class<?> typeClass = propertyDescriptor.getPropertyType(); Class<?> typeClass = f.getType();
Method readMethod = propertyDescriptor.getReadMethod();
BasicField value; BasicField value;
int[] versions = field.version(); int[] versions = field.version();
if (field.type() == DataType.OBJ || field.type() == DataType.LIST) { if (field.type() == DataType.OBJ || field.type() == DataType.LIST) {
if (Collection.class.isAssignableFrom(typeClass)) if (Collection.class.isAssignableFrom(typeClass))
typeClass = (Class<?>) ((ParameterizedType) readMethod.getGenericReturnType()).getActualTypeArguments()[0]; typeClass = (Class<?>) ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0];
loadSchema(root, typeClass); loadRuntimeSchema(root, typeClass);
for (int ver : versions) { for (int ver : versions) {
Map<Integer, Schema<?>> schemaMap = root.getOrDefault(typeClass.getName(), Collections.EMPTY_MAP); Map<Integer, RuntimeSchema<?>> schemaMap = root.getOrDefault(typeClass.getName(), Collections.EMPTY_MAP);
Schema schema = schemaMap.get(ver); RuntimeSchema schema = schemaMap.get(ver);
value = FieldFactory.create(field, propertyDescriptor, schema); value = FieldFactory.create(field, f, schema);
multiVersionFields.get(ver).add(value); multiVersionFields.get(ver).add(value);
} }
} else { } else {
value = FieldFactory.create(field, propertyDescriptor); value = FieldFactory.create(field, f);
for (int ver : versions) { for (int ver : versions) {
multiVersionFields.get(ver).add(value); multiVersionFields.get(ver).add(value);
} }

View File

@ -1,5 +1,7 @@
package io.github.yezhihao.protostar; package io.github.yezhihao.protostar;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import java.util.Map; import java.util.Map;
/** /**
@ -24,15 +26,15 @@ public class ProtostarUtil {
} }
} }
public static Schema getSchema(Object typeId, Integer version) { public static RuntimeSchema getRuntimeSchema(Object typeId, Integer version) {
return LOAD_STRATEGY.getSchema(typeId, version); return LOAD_STRATEGY.getRuntimeSchema(typeId, version);
} }
public static Schema getSchema(Class<?> typeClass, Integer version) { public static RuntimeSchema getRuntimeSchema(Class<?> typeClass, Integer version) {
return LOAD_STRATEGY.getSchema(typeClass, version); return LOAD_STRATEGY.getRuntimeSchema(typeClass, version);
} }
public static <T> Map<Integer, Schema<T>> getSchema(Class<T> typeClass) { public static <T> Map<Integer, RuntimeSchema<T>> getRuntimeSchema(Class<T> typeClass) {
return LOAD_STRATEGY.getSchema(typeClass); return LOAD_STRATEGY.getRuntimeSchema(typeClass);
} }
} }

View File

@ -12,7 +12,7 @@ import java.lang.annotation.Target;
* @author yezhihao * @author yezhihao
* home https://gitee.com/yezhihao/jt808-server * home https://gitee.com/yezhihao/jt808-server
*/ */
@Target(ElementType.METHOD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Convert { public @interface Convert {

View File

@ -9,7 +9,7 @@ import java.lang.annotation.*;
* home https://gitee.com/yezhihao/jt808-server * home https://gitee.com/yezhihao/jt808-server
*/ */
@Repeatable(Fs.class) @Repeatable(Fs.class)
@Target(ElementType.METHOD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Field { public @interface Field {

View File

@ -9,7 +9,7 @@ import java.lang.annotation.Target;
* @author yezhihao * @author yezhihao
* home https://gitee.com/yezhihao/jt808-server * home https://gitee.com/yezhihao/jt808-server
*/ */
@Target(ElementType.METHOD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Fs { public @interface Fs {

View File

@ -6,9 +6,6 @@ import io.netty.buffer.ByteBuf;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
/** /**
* *
* @author yezhihao * @author yezhihao
@ -19,23 +16,21 @@ public abstract class BasicField<T> implements Comparable<BasicField<T>> {
protected final int index; protected final int index;
protected final int length; 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 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(); this.index = field.index();
int length = field.length(); int length = field.length();
if (length < 0) if (length < 0)
length = field.type().length; length = field.type().length;
this.length = length; this.length = length;
this.desc = field.desc();
this.readMethod = property.getReadMethod();
this.writeMethod = property.getWriteMethod();
this.field = field; 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; public abstract boolean readFrom(ByteBuf input, Object message) throws Exception;
@ -62,13 +57,12 @@ public abstract class BasicField<T> implements Comparable<BasicField<T>> {
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(60); final StringBuilder sb = new StringBuilder(50);
sb.append('{'); sb.append('{');
sb.append("index=").append(index); sb.append("index=").append(index);
sb.append(", length=").append(length); sb.append(", length=").append(length);
sb.append(", desc").append(desc); sb.append(", desc").append(field.desc());
sb.append(", readMethod=").append(readMethod.getName()); sb.append(", field=").append(f.getName());
sb.append(", writeMethod=").append(writeMethod.getName());
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }

View File

@ -1,12 +1,10 @@
package io.github.yezhihao.protostar.field; package io.github.yezhihao.protostar.field;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field; import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.util.ByteBufUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; 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<T> extends BasicField<T> {
protected final int lengthSize; protected final int lengthSize;
public DynamicLengthField(Field field, PropertyDescriptor property, Schema<T> schema) { public DynamicLengthField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, property); super(field, f);
this.schema = schema; this.schema = schema;
this.lengthSize = field.lengthSize(); this.lengthSize = field.lengthSize();
} }
@ -30,12 +28,12 @@ public class DynamicLengthField<T> extends BasicField<T> {
if (!input.isReadable(length)) if (!input.isReadable(length))
return false; return false;
Object value = schema.readFrom(input, length); Object value = schema.readFrom(input, length);
writeMethod.invoke(message, value); f.set(message, value);
return true; return true;
} }
public void writeTo(ByteBuf output, Object message) throws Exception { public void writeTo(ByteBuf output, Object message) throws Exception {
Object value = readMethod.invoke(message); Object value = f.get(message);
if (value != null) { if (value != null) {
int begin = output.writerIndex(); int begin = output.writerIndex();
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]); output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
@ -55,8 +53,8 @@ public class DynamicLengthField<T> extends BasicField<T> {
public static class Logger<T> extends DynamicLengthField<T> { public static class Logger<T> extends DynamicLengthField<T> {
public Logger(Field field, PropertyDescriptor property, Schema<T> schema) { public Logger(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, property, schema); super(field, f, schema);
} }
public boolean readFrom(ByteBuf input, Object message) throws Exception { public boolean readFrom(ByteBuf input, Object message) throws Exception {
@ -66,18 +64,18 @@ public class DynamicLengthField<T> extends BasicField<T> {
if (!input.isReadable(length)) if (!input.isReadable(length))
return false; return false;
Object value = schema.readFrom(input, length); Object value = schema.readFrom(input, length);
writeMethod.invoke(message, value); f.set(message, value);
int after = input.readerIndex(); int after = input.readerIndex();
String hex = ByteBufUtil.hexDump(input.slice(before, after - before)); 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; return true;
} }
public void writeTo(ByteBuf output, Object message) throws Exception { public void writeTo(ByteBuf output, Object message) throws Exception {
int before = output.writerIndex(); int before = output.writerIndex();
Object value = readMethod.invoke(message); Object value = f.get(message);
if (value != null) { if (value != null) {
int begin = output.writerIndex(); int begin = output.writerIndex();
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]); output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
@ -88,7 +86,7 @@ public class DynamicLengthField<T> extends BasicField<T> {
int after = output.writerIndex(); int after = output.writerIndex();
String hex = ByteBufUtil.hexDump(output.slice(before, after - before)); String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
println(this.index, this.desc, hex, value); println(this.index, this.field.desc(), hex, value);
} }
} }
} }

View File

@ -1,11 +1,9 @@
package io.github.yezhihao.protostar.field; package io.github.yezhihao.protostar.field;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field; import io.github.yezhihao.protostar.annotation.Field;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.github.yezhihao.protostar.Schema;
import java.beans.PropertyDescriptor;
/** /**
* *
@ -16,51 +14,51 @@ public class FixedField<T> extends BasicField<T> {
protected final Schema<T> schema; protected final Schema<T> schema;
public FixedField(Field field, PropertyDescriptor property, Schema<T> schema) { public FixedField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, property); super(field, f);
this.schema = schema; this.schema = schema;
} }
public boolean readFrom(ByteBuf input, Object message) throws Exception { public boolean readFrom(ByteBuf input, Object message) throws Exception {
Object value = schema.readFrom(input); Object value = schema.readFrom(input);
writeMethod.invoke(message, value); f.set(message, value);
return true; return true;
} }
public void writeTo(ByteBuf output, Object message) throws Exception { public void writeTo(ByteBuf output, Object message) throws Exception {
Object value = readMethod.invoke(message); Object value = f.get(message);
if (value != null) if (value != null)
schema.writeTo(output, (T) value); schema.writeTo(output, (T) value);
} }
public static class Logger<T> extends FixedField<T> { public static class Logger<T> extends FixedField<T> {
public Logger(Field field, PropertyDescriptor property, Schema<T> schema) { public Logger(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, property, schema); super(field, f, schema);
} }
public boolean readFrom(ByteBuf input, Object message) throws Exception { public boolean readFrom(ByteBuf input, Object message) throws Exception {
int before = input.readerIndex(); int before = input.readerIndex();
Object value = schema.readFrom(input); Object value = schema.readFrom(input);
writeMethod.invoke(message, value); f.set(message, value);
int after = input.readerIndex(); int after = input.readerIndex();
String hex = ByteBufUtil.hexDump(input.slice(before, after - before)); 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; return true;
} }
public void writeTo(ByteBuf output, Object message) throws Exception { public void writeTo(ByteBuf output, Object message) throws Exception {
int before = output.writerIndex(); int before = output.writerIndex();
Object value = readMethod.invoke(message); Object value = f.get(message);
if (value != null) if (value != null)
schema.writeTo(output, (T) value); schema.writeTo(output, (T) value);
int after = output.writerIndex(); int after = output.writerIndex();
String hex = ByteBufUtil.hexDump(output.slice(before, after - before)); String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
println(this.index, this.desc, hex, value); println(this.index, this.field.desc(), hex, value);
} }
} }
} }

View File

@ -1,11 +1,9 @@
package io.github.yezhihao.protostar.field; package io.github.yezhihao.protostar.field;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field; import io.github.yezhihao.protostar.annotation.Field;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.github.yezhihao.protostar.Schema;
import java.beans.PropertyDescriptor;
/** /**
* *
@ -16,51 +14,51 @@ public class FixedLengthField<T> extends BasicField<T> {
protected final Schema<T> schema; protected final Schema<T> schema;
public FixedLengthField(Field field, PropertyDescriptor property, Schema<T> schema) { public FixedLengthField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, property); super(field, f);
this.schema = schema; this.schema = schema;
} }
public boolean readFrom(ByteBuf input, Object message) throws Exception { public boolean readFrom(ByteBuf input, Object message) throws Exception {
Object value = schema.readFrom(input, length); Object value = schema.readFrom(input, length);
writeMethod.invoke(message, value); f.set(message, value);
return true; return true;
} }
public void writeTo(ByteBuf output, Object message) throws Exception { public void writeTo(ByteBuf output, Object message) throws Exception {
Object value = readMethod.invoke(message); Object value = f.get(message);
if (value != null) if (value != null)
schema.writeTo(output, length, (T) value); schema.writeTo(output, length, (T) value);
} }
public static class Logger<T> extends FixedLengthField<T> { public static class Logger<T> extends FixedLengthField<T> {
public Logger(Field field, PropertyDescriptor property, Schema<T> schema) { public Logger(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, property, schema); super(field, f, schema);
} }
public boolean readFrom(ByteBuf input, Object message) throws Exception { public boolean readFrom(ByteBuf input, Object message) throws Exception {
int before = input.readerIndex(); int before = input.readerIndex();
Object value = schema.readFrom(input, length); Object value = schema.readFrom(input, length);
writeMethod.invoke(message, value); f.set(message, value);
int after = input.readerIndex(); int after = input.readerIndex();
String hex = ByteBufUtil.hexDump(input.slice(before, after - before)); 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; return true;
} }
public void writeTo(ByteBuf output, Object message) throws Exception { public void writeTo(ByteBuf output, Object message) throws Exception {
int before = output.writerIndex(); int before = output.writerIndex();
Object value = readMethod.invoke(message); Object value = f.get(message);
if (value != null) if (value != null)
schema.writeTo(output, length, (T) value); schema.writeTo(output, length, (T) value);
int after = output.writerIndex(); int after = output.writerIndex();
String hex = ByteBufUtil.hexDump(output.slice(before, after - before)); String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
println(this.index, this.desc, hex, value); println(this.index, this.field.desc(), hex, value);
} }
} }
} }

View File

@ -34,6 +34,29 @@ public class RuntimeSchema<T> implements Schema<T> {
} }
} }
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) { public T readFrom(ByteBuf input) {
BasicField field = null; BasicField field = null;
try { try {

View File

@ -5,7 +5,9 @@ import io.github.yezhihao.protostar.annotation.Field;
public class Attr1 { public class Attr1 {
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称")
private String name; private String name;
@Field(index = 1, type = DataType.WORD, desc = "ID")
private int id; private int id;
public Attr1() { public Attr1() {
@ -16,7 +18,6 @@ public class Attr1 {
this.id = id; this.id = id;
} }
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称")
public String getName() { public String getName() {
return name; return name;
} }
@ -25,7 +26,6 @@ public class Attr1 {
this.name = name; this.name = name;
} }
@Field(index = 1, type = DataType.WORD, desc = "ID")
public int getId() { public int getId() {
return id; return id;
} }

View File

@ -2,10 +2,9 @@ package io.github.yezhihao.protostar.convert;
import io.github.yezhihao.protostar.DataType; import io.github.yezhihao.protostar.DataType;
import io.github.yezhihao.protostar.ProtostarUtil; 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.Convert;
import io.github.yezhihao.protostar.annotation.Field; 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.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@ -17,9 +16,9 @@ import java.util.TreeMap;
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
Map<Integer, Schema<Foo>> multiVersionSchema = ProtostarUtil.getSchema(Foo.class); Map<Integer, RuntimeSchema<Foo>> multiVersionSchema = ProtostarUtil.getRuntimeSchema(Foo.class);
Schema<Foo> schema_v0 = multiVersionSchema.get(0); RuntimeSchema<Foo> schema_v0 = multiVersionSchema.get(0);
Schema<Foo> schema_v1 = multiVersionSchema.get(1); RuntimeSchema<Foo> schema_v1 = multiVersionSchema.get(1);
ByteBuf buffer = Unpooled.buffer(32); ByteBuf buffer = Unpooled.buffer(32);
schema_v0.writeTo(buffer, foo()); schema_v0.writeTo(buffer, foo());
@ -56,13 +55,18 @@ public class Test {
public static class Foo { 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; 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; private int id;
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
private LocalDateTime dateTime; private LocalDateTime dateTime;
@Convert(converter = AttributeConverter.class)
@Field(index = 4, type = DataType.MAP, desc = "属性", version = {0, 1})
private Map<Integer, Object> attributes; private Map<Integer, Object> 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() { public String getName() {
return name; return name;
} }
@ -71,8 +75,6 @@ public class Test {
this.name = name; 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() { public int getId() {
return id; return id;
} }
@ -81,7 +83,6 @@ public class Test {
this.id = id; this.id = id;
} }
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
public LocalDateTime getDateTime() { public LocalDateTime getDateTime() {
return dateTime; return dateTime;
} }
@ -90,8 +91,6 @@ public class Test {
this.dateTime = dateTime; this.dateTime = dateTime;
} }
@Convert(converter = AttributeConverter.class)
@Field(index = 4, type = DataType.MAP, desc = "属性", version = {0, 1})
public Map<Integer, Object> getAttributes() { public Map<Integer, Object> getAttributes() {
return attributes; return attributes;
} }

View File

@ -2,8 +2,8 @@ package io.github.yezhihao.protostar.multiversion;
import io.github.yezhihao.protostar.DataType; import io.github.yezhihao.protostar.DataType;
import io.github.yezhihao.protostar.ProtostarUtil; import io.github.yezhihao.protostar.ProtostarUtil;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field; import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@ -14,9 +14,9 @@ import java.util.Map;
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
Map<Integer, Schema<Foo>> multiVersionSchema = ProtostarUtil.getSchema(Foo.class); Map<Integer, RuntimeSchema<Foo>> multiVersionSchema = ProtostarUtil.getRuntimeSchema(Foo.class);
Schema<Foo> schema_v0 = multiVersionSchema.get(0); RuntimeSchema<Foo> schema_v0 = multiVersionSchema.get(0);
Schema<Foo> schema_v1 = multiVersionSchema.get(1); RuntimeSchema<Foo> schema_v1 = multiVersionSchema.get(1);
ByteBuf buffer = Unpooled.buffer(32); ByteBuf buffer = Unpooled.buffer(32);
Foo foo = foo(); Foo foo = foo();
@ -48,12 +48,15 @@ public class Test {
public static class Foo { 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, lengthSize = 1, desc = "名称", version = 0)
@Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1) @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() { public String getName() {
return name; return name;
} }
@ -62,8 +65,6 @@ public class Test {
this.name = name; 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() { public int getId() {
return id; return id;
} }
@ -72,7 +73,6 @@ public class Test {
this.id = id; this.id = id;
} }
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
public LocalDateTime getDateTime() { public LocalDateTime getDateTime() {
return dateTime; return dateTime;
} }

View File

@ -3,8 +3,8 @@ package io.github.yezhihao.protostar.simple;
import io.github.yezhihao.protostar.DataType; import io.github.yezhihao.protostar.DataType;
import io.github.yezhihao.protostar.FieldFactory; import io.github.yezhihao.protostar.FieldFactory;
import io.github.yezhihao.protostar.ProtostarUtil; import io.github.yezhihao.protostar.ProtostarUtil;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field; import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@ -17,16 +17,24 @@ public class Test {
public static void main(String[] args) { public static void main(String[] args) {
FieldFactory.EXPLAIN = true; FieldFactory.EXPLAIN = true;
Map<Integer, Schema<Foo>> multiVersionSchema = ProtostarUtil.getSchema(Foo.class); Map<Integer, RuntimeSchema<Foo>> bodySchemas = ProtostarUtil.getRuntimeSchema(Foo.class);
Schema<Foo> schema = multiVersionSchema.get(0); RuntimeSchema<Foo> bodySchema = bodySchemas.get(0);
Map<Integer, RuntimeSchema<BaseDO>> headSchemas = ProtostarUtil.getRuntimeSchema(BaseDO.class);
RuntimeSchema<BaseDO> headSchema = headSchemas.get(0);
ByteBuf buffer = Unpooled.buffer(32); ByteBuf buffer = Unpooled.buffer(32);
Foo foo = foo(); Foo foo = foo();
schema.writeTo(buffer, foo); headSchema.writeTo(buffer, foo);
bodySchema.writeTo(buffer, foo);
String hex = ByteBufUtil.hexDump(buffer); String hex = ByteBufUtil.hexDump(buffer);
System.out.println(hex); System.out.println(hex);
foo = schema.readFrom(buffer);
Foo foo1 = new Foo();
headSchema.mergeFrom(buffer, foo1);
bodySchema.mergeFrom(buffer, foo1);
System.out.println(foo); System.out.println(foo);
} }
@ -35,16 +43,45 @@ public class Test {
foo.setName("张三"); foo.setName("张三");
foo.setId(128); foo.setId(128);
foo.setDateTime(LocalDateTime.of(2020, 7, 7, 19, 23, 59)); foo.setDateTime(LocalDateTime.of(2020, 7, 7, 19, 23, 59));
foo.setType(1);
foo.setClientId("123qwe");
return foo; return foo;
} }
public static class Foo { public static class BaseDO {
private String name; @Field(index = 0, type = DataType.WORD, desc = "ID")
private int id; protected int type;
private LocalDateTime dateTime; @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 = "名称") @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() { public String getName() {
return name; return name;
} }
@ -53,7 +90,6 @@ public class Test {
this.name = name; this.name = name;
} }
@Field(index = 1, type = DataType.WORD, desc = "ID")
public int getId() { public int getId() {
return id; return id;
} }
@ -62,7 +98,6 @@ public class Test {
this.id = id; this.id = id;
} }
@Field(index = 3, type = DataType.BCD8421, desc = "日期")
public LocalDateTime getDateTime() { public LocalDateTime getDateTime() {
return dateTime; return dateTime;
} }
@ -74,7 +109,9 @@ public class Test {
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder("Foo{"); 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(", id=").append(id);
sb.append(", dateTime=").append(dateTime); sb.append(", dateTime=").append(dateTime);
sb.append('}'); sb.append('}');