Spring源码学习系列(一)之初探xml解析
2019-06-27 本文已影响0人
just_like_you
1、从简单的xml解析bean开始
BeanFactory factory = new BeanFactory(new ClassPathResource("beans.xml"));
YourBean bean = factory.getBean(YourBean.class);
1.1、上面一共做了两个比较重要的动作
- 加载
beans.xml
配置文件 - 构造BeanFactory
1.2、怎么加载*.xml
配置文件?
ClassPathResource
是Resource
的一个实现类,而Resource
是Spring的一个对java底层URL的增强抽象,里面包括是否可读,还有转化为URL,File等方法。在ClassPathResource
中是通过类加载来加载类路径下的资源,而FileSystemResource
是直接通过FileIntputStream
来获取文件资源。

1.3、BeanFactory的构造、初始化过程
-
XmlBeanFactory构造器
构造器情况
- 在调用父类的构造器的时候会设置忽略的Bean信息,这里的
IgnoreDependencyInterface(xxx.class)
的作用是将实现xxx.class的实现类(图中的BeanNameAware.class..)中的含有该接口的setter包含的属性的值忽略自动注入,如图1-1,将自动忽略BeanNameAware
子类中BeanName属性的自动注入
忽略bean注入信息

- 委托给
XmlBeanDefinitionReader.loadBeanDefinitions(Resource)
来进行加载配置信息 - 使用
EncodeResource
对Resource
进行编码包装
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
- 进行解析准备阶段
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
.....校验
// 将资源绑定到当前线程
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//这里会将Resource的输入流拿到然后转化为xml中的IntputSource
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//执行加载的主要逻辑
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
.....关闭资源
}
- 进行到处理加载
xml
配置的主方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// SAX解析为xml的Document对象
Document doc = doLoadDocument(inputSource, resource);
// 注册BeanDefinition并返回数量
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
- 其中
doLoadDocument()源码
当中主要getValidationModeForResource
会根据传递的xml的解析方法(DTD,XSD)来校验当前文件的格式是否正确
getEntityResolver()
主要是避免网络获取(DTD,XSD)的标准文件,通过本地文件系统(DTD)或META-INF/spring.factories(XSD)下来加快程序的运行
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
- 然后就是通过
DocumentBuilderFactory
来进行标准的SAX解析,从而获取到配置文件的Document
对象
标准sax解析
完结,下一章注册BeanDefinition