本文介紹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無父對象。