哦,哦,有人对XJC内部感兴趣。我可能会有所帮助,因为我可能开发的 JAXB 插件比其他任何人都多(例如,请参阅JAXB2 基础知识)
好的,让我们开始吧。在 XJC 中,模式编译器大约执行以下操作
- 解析架构
- 创建模式的模型(CClass、CPropertyInfo 等)
- 创建大纲(ClassOutline、FieldOutline 等)
- 呈现代码模型(JClass、JDefinedClass、JMethod 等)
- 写入物理代码(例如磁盘上的 Java 文件)
让我们从最后两个开始。
我希望 Java 文件不需要解释。
代码模型也是一件相对容易的事情。它是一种 API,可用于以编程方式构造 Java 代码。您可以只使用字符串连接,但它更容易出错。使用 CodeModel,您几乎可以保证获得至少语法正确的 Java 代码。所以我希望这部分也很清楚。(顺便说一句,我非常喜欢 CodeModel。最近根据 CodeModel 的想法编写了JavaScript Code Model 。)
现在让我们看看“模型”和“轮廓”。模型是解析传入模式的结果。它对传入模式的构造进行建模,主要根据对应于复杂类型的“类”和对应于元素、属性和值的“属性”(例如,当您拥有具有简单内容的复杂类型时)。
该模型应该被理解为接近 XML 和模式的逻辑建模结构。因此,它只描述了它们拥有的类型和属性。它肯定比我描述它的方式复杂得多,有各种各样的例外和警告——从通配符类型(xsd:any)、替换组、枚举、内置类型等等开始。
非常有趣的是,在运行时 JAXB 使用了Model
is的兄弟。RuntimeTypeInfoSetImpl
所以它也是一种模型——然而它不是从 XML Schema 中解析出来的,而是从类中的 JAXB 注释中解析出来的。概念是一样的。模型和RuntimeTypeInfoSetImpl
实现TypeInfoSet
都是超结构的接口。检查像ClassInfo
和这样的接口PropertyInfo
——它们在编译时(CClassInfo
以及CPropertyInfo
在 XJC 中)和运行时(RuntimeClassInfoImpl
对于 JAXB RI 等)都有实现。
好的,所以当 XJC 解析和分析模式时,你得到了Model
. 这Model
还不能生成代码。事实上,产生代码的策略不同。您可以只生成带注释的类,也可以像在 JAXB 1 中那样生成接口/实现类对。整个代码生成实际上并不是模型的任务。此外,还有许多方面与 Java 代码的物理性质相关,但与模型并不真正相关。例如,您必须将类分组到包中。这是由 Java 的打包系统驱动的,而不是由模型本身的属性驱动的。
这就是大纲发挥作用的地方。您可以将大纲视为模式模型和代码模型之间的步骤。您可以将大纲视为负责组织代码和从s生成JDefinedClass
es的代码模型元素的工厂。CClassInfo
所以你是对的,它确实非常复杂。我不是 Sun/Oracle 的员工,不是我设计的(不过我认识做这件事的人,并且非常尊重他)。我可以猜测某些设计决策的几个原因,例如:
- 对编译时和运行时模型使用相同的接口
- 允许不同的代码生成策略
- 允许插件操作创建的模型
我同意这个设计非常复杂,但它有它的原因。一个证明是,实际上可以为 XML 到 JavaScript 的映射构建一个映射生成器——基本上在相同的模型上。我只需要替换代码生成,保持模式分析不变。(请参阅Jsonix。)
好的,希望我能阐明为什么 XJC 中的事情是这样的。祝这些 API 好运,它们并不简单。随意检查现有的开源代码,有很多可用的示例。
附言。真的一直想写这个。:)