本文介绍Java代码扫描与平台模型映射的特殊规则。
Java类型与平台类型映射
所有的映射通过插件上报都会在元数据中记录代码中的实际类型,再次生成代码时可以原样生成。但通过平台上报的类型可能会丢失真实的类型信息。
基础类型、包装类型映射
Java基础类型扫描上报成对应包装类型:例如:int -> Integer , boolean -> Boolean。
数组、集合类型映射
数组扫描上报为建模平台中的List。
继承或实现java.util.Collection,且非继承或实现java.util.Set的类型扫描上报为建模平台中的List,例如List、ArrayList等。
继承或实现java.util.Set的类型扫描上报为建模平台中的Set,例如:Set、HashSet等。
继承或实现java.util.Map的类型扫描上报为建模平台中的Map,例如:Map、HashMap等。
泛型类型映射
泛型类型使用
泛型类型会实例化为一个结构对象上报。
泛型类型的使用,会去掉尖括号,将类型与类型参数拼接在一起成为新的结构对象Code,示例如下。
GenericExample<ObjectA> -> GenericExampleObjectA
GenericExample<GenericExample<ObjectB> -> GenericExampleGenericExampleObjectB
如果泛型使用并未提供参数类型,或使用单个通配符?
,则默认参数类型为Object。如果,泛型的参数类型使用通配符表达则取其上界类型。示例如下。
GenericExample -> GenericExampleObject
GenericExample<?> -> GenericExampleObject
GenericExample<? extends ObjectA> -> GenericExampleObjectA
泛型类型定义
泛型类型的定义扫描上报的时候,类名会去掉类型参数原样上报,参数类型在类内部的使用会使用其上界替换。具体如下代码示例所示。
public class Demo<T> { private T f; }
public class Demo2<T extends Demo3DTO> { private T f; }
上述的两个示例,上报后分别为Demo
和Demo2
两个结构对象。
Demo
的字段f
类型会被扫描上报为Object
。Demo2
的字段f
类型会被扫描上报为Demo3DTO
。
枚举类型映射
当前平台对枚举类型无特殊处理,扫描的时候会作为一个普通的结构对象上报。
不深入扫描解析的场景
特定的包
对一些公共包下的类,其内容、结构等对业务模型设计使用基本无影响,则认为无进一步解析必要,仅会上报类型名,以保证平台类型依赖正确。当前不解析的包有:
"java.",
"javax.",
"org.slf4j",
"org.apache.commons.logging",
"org.springframework.context",
"sun"
一定的依赖深度
当前扫描,对于未标记为模型,但被模型依赖到(例如:字段类型、方法出入参、继承类型等)的普通Java类型,会作为结构对象扫描上报到平台。
例如,A为结构对象,B、C、D、E为普通Java类无注解。但A的字段f1
类型为B,这种情况下认为A的类型表达依赖B的类型,即A -> B。同样,我们假设A -> B,A -> C,B -> D,D -> E。A对B、C直接依赖,对D、E间接依赖。则除了A本身被扫描为结构对象,B、C、D、E都会被扫描为结构对象。
为防止代码中模型依赖的其他类(未标记为模型)依赖关系不断传递、层级过深,故扫描过程以标记的模型为出发点,目前最多只解析n层依赖深度。到达n层后,仅上报类型名,以保证平台类型依赖正确。
当前依赖深度层数n不可配置,固定为3。
其他特殊映射
继承关系
平台内置基本类型包含Date与BigDecimal。Java中java.util.Date和java.math.BigDecimal扫描上报会被映射为平台的这两种基本类型。
因为平台暂不支持继承基本类型,故在Java中继承java.util.Date和java.math.BigDecimal的继承关系在扫描上报的时候会被忽略。例如,class CustomDateTime extends java.util.Date{},上报到平台后CustomDateTime无父对象。