perf[protocol]: 添加协议号对注解的支持

This commit is contained in:
meiwei
2022-07-29 12:20:25 +08:00
parent b611d1e2e0
commit 0858e32188
4 changed files with 75 additions and 42 deletions
@@ -16,7 +16,8 @@ package com.zfoo.protocol.generate;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.serializer.anno.Description;
import com.zfoo.protocol.serializer.anno.ProtocolClass;
import com.zfoo.protocol.serializer.anno.ProtocolField;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.StringUtils;
@@ -72,25 +73,24 @@ public abstract class GenerateProtocolDocument {
public static void initProtocolDocument(List<IProtocolRegistration> protocolRegistrations) {
AssertionUtils.notNull(protocolDocumentMap, "[{}]已经初始完成,初始化完成过后不能调用initProtocolDocument", GenerateProtocolDocument.class.getSimpleName());
// 文件的注释生成
for (var protocolRegistration : protocolRegistrations) {
var protocolClazz = protocolRegistration.protocolConstructor().getDeclaringClass();
var docFieldMap = new HashMap<String, String>();
var docTitle = StringUtils.EMPTY;
var description = protocolClazz.getDeclaredAnnotation(Description.class);
if (description != null) {
var docTitleBuilder = new StringBuilder().append("//").append(description.value());
var protocolClass = protocolClazz.getDeclaredAnnotation(ProtocolClass.class);
if (protocolClass != null && StringUtils.isNotEmpty(protocolClass.description())) {
var docTitleBuilder = new StringBuilder().append("//").append(protocolClass.description());
docTitle = docTitleBuilder.toString();
}
var registration = (ProtocolRegistration) protocolRegistration;
for (var field : registration.getFields()) {
var fieldDescrption = field.getDeclaredAnnotation(Description.class);
if (fieldDescrption == null) {
var protocolField = field.getDeclaredAnnotation(ProtocolField.class);
if (protocolField == null || StringUtils.isEmpty(protocolField.description())) {
continue;
}
var docBuilder = new StringBuilder().append("//").append(fieldDescrption.value());
var docBuilder = new StringBuilder().append("//").append(protocolField.description());
var fieldName = field.getName();
docFieldMap.put(fieldName, docBuilder.toString());
}
@@ -24,6 +24,7 @@ import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.generate.GenerateProtocolPath;
import com.zfoo.protocol.registration.anno.Compatible;
import com.zfoo.protocol.registration.field.*;
import com.zfoo.protocol.serializer.anno.ProtocolClass;
import com.zfoo.protocol.serializer.cpp.GenerateCppUtils;
import com.zfoo.protocol.serializer.csharp.GenerateCsUtils;
import com.zfoo.protocol.serializer.gdscript.GenerateGdUtils;
@@ -448,11 +449,6 @@ public class ProtocolAnalysis {
return allSubProtocolIdSet;
}
public static short getProtocolIdByClass(Class<?> clazz) {
var protocolIdField = ReflectionUtils.getFieldByNameInPOJOClass(clazz, PROTOCOL_ID);
return (short) ReflectionUtils.getField(protocolIdField, null);
}
// 协议智能语法分析,错误的协议定义将无法启动程序并给出错误警告
//-----------------------------------------------------------------------
@@ -464,13 +460,49 @@ public class ProtocolAnalysis {
// 不能是泛型类
AssertionUtils.isTrue(ArrayUtils.isEmpty(clazz.getTypeParameters()), "[class:{}]不能是泛型类", clazz.getCanonicalName());
Field protocolIdField;
var protocolId = getProtocolIdByClass(clazz);
// 验证protocol()方法的返回是否和PROTOCOL_ID相等
Method protocolMethod;
try {
protocolMethod = clazz.getDeclaredMethod(PROTOCOL_METHOD);
} catch (NoSuchMethodException e) {
protocolMethod = null;
}
if (protocolMethod != null) {
// 必须要有一个空的构造器
Constructor<?> constructor = ReflectionUtils.publicEmptyConstructor(clazz);
IPacket packet = (IPacket) constructor.newInstance();
var methodReturnId = (short) protocolMethod.invoke(packet);
AssertionUtils.isTrue(methodReturnId == protocolId, "[class:{}]的protocolId方法返回的值[{}]和协议号返回值[{}]不相等", clazz.getCanonicalName(), methodReturnId, protocolId);
}
var previous = protocolClassMap.put(protocolId, clazz);
if (previous != null) {
throw new RunException("[{}][{}]协议号[protocolId:{}]重复", clazz.getCanonicalName(), previous.getCanonicalName(), protocolId);
}
//存储class和protocolId的映射
protocolIdMap.put(clazz, protocolId);
}
public static short getProtocolIdByClass(Class<?> clazz) {
var protocolClass = clazz.getDeclaredAnnotation(ProtocolClass.class);
short annoProtocolId = 0;
if (protocolClass != null && protocolClass.protocolId() != 0) {
annoProtocolId = protocolClass.protocolId();
}
Field protocolIdField = null;
try {
protocolIdField = clazz.getDeclaredField(PROTOCOL_ID);
} catch (NoSuchFieldException e) {
throw new UnknownException(e, "[class:{}]没有[{}]协议序列号", clazz.getCanonicalName(), PROTOCOL_ID);
if (annoProtocolId != 0) {
return annoProtocolId;
}
}
// 是否被public修饰
AssertionUtils.isTrue(protocolIdField != null, "[class:{}]协议序列号[{}]没有被public修饰", clazz.getCanonicalName(), PROTOCOL_ID);
// 是否被public修饰
AssertionUtils.isTrue(Modifier.isPublic(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被public修饰", clazz.getCanonicalName(), PROTOCOL_ID);
// 是否被static修饰
@@ -481,31 +513,13 @@ public class ProtocolAnalysis {
AssertionUtils.isTrue(Modifier.isTransient(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被transient修饰", clazz.getCanonicalName(), PROTOCOL_ID);
// 命名只能包含字母,数字,下划线
AssertionUtils.isTrue(clazz.getSimpleName().matches("[a-zA-Z0-9_]*"), "[class:{}]的命名只能包含字母,数字,下划线", clazz.getCanonicalName(), PROTOCOL_ID);
// 必须要有一个空的构造器
Constructor<?> constructor = ReflectionUtils.publicEmptyConstructor(clazz);
ReflectionUtils.makeAccessible(protocolIdField);
IPacket packet = (IPacket) constructor.newInstance();
var protocolId = (short) protocolIdField.get(null);
// 验证protocol()方法的返回是否和PROTOCOL_ID相等
Method protocolMethod;
try {
protocolMethod = clazz.getDeclaredMethod(PROTOCOL_METHOD);
} catch (NoSuchMethodException e) {
protocolMethod = null;
var protocolId = (short) ReflectionUtils.getField(protocolIdField, null);
if (annoProtocolId != 0) {
AssertionUtils.isTrue(annoProtocolId == protocolId, "[class:{}]协议序列号[{}]:[{}]与注解协议号[{}]值不相等", clazz.getCanonicalName(), PROTOCOL_ID, protocolId, annoProtocolId);
}
if (protocolMethod != null) {
var methodReturnId = (short) protocolMethod.invoke(packet);
AssertionUtils.isTrue(methodReturnId == protocolId, "[class:{}]的protocolId返回的值和协议号的静态变量[{}]不相等", clazz.getCanonicalName(), PROTOCOL_ID);
}
var previous = protocolClassMap.put(protocolId, clazz);
if (previous != null) {
throw new RunException("[{}][{}]协议号[protocolId:{}]重复", clazz.getCanonicalName(), previous.getCanonicalName(), protocolId);
}
//存储class和protocolId的映射
protocolIdMap.put(clazz, protocolId);
return protocolId;
}
private static void checkSubProtocol(Class<?> clazz, short id, Class<?> subClass) {
@@ -0,0 +1,19 @@
package com.zfoo.protocol.serializer.anno;
import java.lang.annotation.*;
/**
* @author meiw
* @version 3.0
*
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ProtocolClass {
short protocolId() default 0;
String description() default "";
}
@@ -9,9 +9,9 @@ import java.lang.annotation.*;
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Description {
@Target({ElementType.FIELD})
public @interface ProtocolField {
String value() default "";
String description() default "";
}