一个spring加载xsd问题的跟踪

先列下原配置 

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

运行时异常

2020-01-10 11:28:07.822-[WARN] org.springframework.util.xml.SimpleSaxErrorHandler.warning(SimpleSaxErrorHandler.java:48) Ignored XML validation warning
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/beans/spring-beans.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
    at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source) ~[xercesImpl-2.9.1.jar:?]
显示不能读取到  'http://www.springframework.org/schema/beans/spring-beans.xsd'

于是在网上查询相关信息, 大概是在        http://www.springframework.org/schema/beans/spring-beans.xsd  这个配置可以加序列号和不加序列号, 加序列号会加载到特定版本的xsd , 不加版本包会加载到当前版本的xsd ,笔者用的版本是5.1.7。(优先本地加载, 本地加载不到会到sping的官网加载,笔者出现的错误是在屏蔽spring官网的情况下,为了模拟线上机房不能连接外网的情况)但是为什么加载不到本地文件呢,去查询相关资料 。

 

在spring源码的DelegatingEntityResolver类中,看到看到spring通过xml加载bean的时候会判断是DTD规范还是xsd规范 , 我们用的是xsd :

进入 resolveEntity 方法,发现会以systemId为key根据一个map获取资源位置:

进入方法看下具体的map, 是一个size为254的map,

查看SystemId在这个map对应的key——value ,竟然是  org/springframework/beans/factory/xml/spring-beans-4.1.xsd

了解spring通过xml加载bean机制的同学应该知道, 这些这个map是从spring的spring.schema配置里加载的,代码也印证了这一点,会默认从 META-INF/spring.schemas 加载

 

看下我们5.1.7的spring.schema配置,发现无论是否有版本号都只指向一个文件  

org/springframework/beans/factory/xml/spring-beans.xsd

打开5.1.7的jar包发现也确实只有这一个文件


 

目前看来事情的元凶是加载的时候需要找到spring-beans-4.1.xsd文件,但是我们的jar中不存在,所以抛出了异常

事情到这里很奇怪了,为什么spring对应的schemaMap会指向org/springframework/beans/factory/xml/spring-beans-4.1.xsd ,继续跟踪:

在idea中搜索   spring.schema  会发下找到十余个文件,这个笔者猜想是spring在加载配置时候,spring是把所有的文件依次加载进这个Map中, 由于key出现了冲突,最终展现的map没有完全按照5.1.7包下的配置, 至于在加载过程中发生了什么, 如何调整加载顺序,笔者现在对classLoader还不熟悉,暂时无法给出解答。

Properties mappings =
      PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);

最终的解决方式是在map中找到一个value为对应文件的key, 将spring bean的xml配置修改为这个key,就会指向对应的文件:

 

 

由于时间有限,最终加载过程还是没有探究清楚,日后再查。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值