在dubbo源码解析第一章里,我们知道了在dubbo启动(也即spring启动)过程中,是先要加载相关的xml配置文件的,比如provider.xml,consumer.xml或者spring的applicationContextContext.xml都是需要先被加载到内存中去的,这个加载的入口在XmlBeanDefinitionReader类的 doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法里,代码如下
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException
{
try
{
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
...
}
顺着doLoadDocument方法一路跟下去,就可以理出加载xml配置文件的整个流程,我梳理成下 图1:
下载图1
类图结构如下 图2
下载图2
看图2中XmlBeanDefinitionReader依赖ResourceEntityResolver,ResourceEntityResolver是DelegatingEntityResolver的子类,最终依赖的是PluggableSchemaResolver,PluggableSchemaResolver中会获取当前文件所属模块下的META-INFO/spring.schemas文件
这个spring.schemas中又是什么内容呢?打开dubbo中的一个看一下
http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd
我们再找一个spring的子模块spirng-webmvc下的一个schema文件来看一下
http\://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd
http\://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd=org/springframework/web/servlet/config/spring-mvc-3.1.xsd
http\://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd=org/springframework/web/servlet/config/spring-mvc-3.2.xsd
http\://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd=org/springframework/web/servlet/config/spring-mvc-4.0.xsd
http\://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd=org/springframework/web/servlet/config/spring-mvc-4.1.xsd
http\://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd=org/springframework/web/servlet/config/spring-mvc-4.2.xsd
http\://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd=org/springframework/web/servlet/config/spring-mvc-4.3.xsd
http\://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc-4.3.xsd
我们可以发现,都是将一个网络URL指向一个相对路径上去,如果你有源码,你在相对路径上去看下,一定会找到对应的xsd文件。
我们拿个标准的spring的applicationContext.xml配置文件看下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" default-autowire="byName">
<mvc:annotation-driven/>
<import resource="classpath*:/spring/beans-*.xml"/>
<context:component-scan base-package="cn.htd.*"/>
<context:property-placeholder location="classpath:application-env.properties"/>
<!-- <context:annotation-config/> -->
</beans>
重点关注节点中的xsi:schemaLocation这一属性中的内容,可以发现,其中都是完整的网络路径,而实际开发过程中,我们即使不联网,貌似这些xml也是可以正常编译的,是吧?
此时,你是不是有点明白了。
正是这样,EntityResolver 的作用就是项目本身就可以提供一个如何寻找XSD或DTD文件的声明方法,他首先会读取该xml文档上的声明,根据声明去寻找相应的XSD或DTD定义,以便对文档的进行验证,
默认的寻找规则是从META-INF/spring.schemas文件读取。