XMLBeans3.1.0升5.1.0后XmlObject.Factory.parse返回类型异常
XMLBeans 5.1.0版本
XmlObject.Factory.parse返回XmlAnyTypeImpl问题解决方案 问题根因
XMLBeans从4.0版本开始调整了全局类型系统的默认加载逻辑:3.x版本默认会在类加载时自动扫描classpath下所有由schemacompiler生成的XML类型元数据(即各jar包中schemaorg_apache_xmlbeans路径下的TypeSystemHolder配置),通用入口XmlObject.Factory.parse解析时可以自动匹配XML根节点、命名空间对应的生成Document类型;5.x版本为了降低启动开销、避免不必要的全路径扫描,默认关闭了全局自动类型注册,通用parse方法找不到对应类型映射时,就会直接返回通用的XmlAnyTypeImpl实例,不会自动绑定生成类。
直接调用具体生成类的Factory.parse方法时,解析逻辑会直接加载该类关联的schema定义,不依赖全局类型扫描,因此可以正常返回目标类型对象。
可行解决方案
按推荐优先级从高到低排列:
- 方案1:直接调用目标生成类的Factory解析方法
这是官方推荐的最优写法,没有额外的全局扫描开销,编译期即可做类型校验,不存在类型匹配失败的风险,也就是已经验证可行的写法:
如果业务中存在动态解析不同类型XML的场景,可以先通过StAX等轻量方式读取XML的根节点名、命名空间,路由到对应生成类的parse方法即可。SORAccountReadResponseDocument xmlObj = SORAccountReadResponseDocument.Factory.parse(content,opts); - 方案2:应用启动时显式初始化全局类型系统
如果不想改动原有调用XmlObject.Factory.parse的存量代码,可以在应用所有XML解析逻辑执行前(比如启动类的静态块、容器初始化前的钩子),添加一行代码触发全局类型加载:
初始化完成后,通用// 扫描当前上下文类加载器下所有XMLBeans类型元数据并注册到全局 org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader( Thread.currentThread().getContextClassLoader(), "schemaorg_apache_xmlbeans.system" ).resolve();XmlObject.Factory.parse方法的行为就会和3.1.0版本完全一致,自动匹配对应生成类型。 - 方案3:JVM参数开启旧版类型加载逻辑
不方便修改代码的场景,可以在应用启动时添加JVM参数,让5.x版本回退到3.x的类加载逻辑:
该方案不需要改动任何业务代码,但会增加应用启动阶段的类扫描耗时,适合临时兼容老版本逻辑使用。-Dorg.apache.xmlbeans.LEGACY_TYPE_LOADING=true
注意事项
如果采用方案2或方案3,需要确保所有存放XMLBeans生成类的jar包,对传入typeSystemForClassLoader的类加载器可见,否则会出现部分类型无法匹配、仍然返回XmlAnyTypeImpl的问题。
内容的提问来源于stack exchange,提问作者Huynh Dragon
相关产品推荐
相关产品推荐

