• XmlBeanDefinitionReader解读


    XmlBeanDefinitionReader解读

    XmlBeanDefinitionReader介绍

    XmlBeanDefinitionReaderBeanDefinitionReader三大读取器的其中一个,XmlBeanDefinitionReader继承于AbstractBeanDefinitionReaderXmlBeanDefinitionReader是为了读取Xml文件中的Bean而设计出来的。

    AbstractBeanDefinitionReader内部有registry成员属性,理所当然可以往IOC容器里面添加BeanDefinition。XmlBeanDefinitionReader继承于AbstractBeanDefinitionReader,必定也能将BeanDefinition注册到容器里面。

    请记住这个AbstractBeanDefinitionReader中的成员属性,因为后面XmlBeanDefinitionReader会通过调用AbstractBeanDefinitionReader的getRegistry()拿到这个成员属性

    //AbstractBeanDefinitionReader的私有成员属性
    private final BeanDefinitionRegistry registry;
    
    //AbstractBeanDefinitionReader中的公共方法
    @Override
    public final BeanDefinitionRegistry getRegistry() {
        return this.registry;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    DTD和XSD

    • DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
    • XSD(XML Schema Definition)的作用是定义一份XML文档的合法组件群,就像文档类型定义(外语缩写:DTD)的作用一样。XML Schema 比 DTD 更强大。

    其实两者都是用来定义和约束XML的结构信息的,如:有哪些节点,节点之间的结构关系等等。

    我们平时的bean定义的xml文件里面的xmlns:xsi , xsi:schemaLocation就是XSD,用来约束xml文件结构。

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    </beans>
    
    • 1
    • 2
    • 3
    • 4

    XmlBeanDefinitionReader源码

    XmlBeanDefinitionReader一些关键成员属性

    从注释就可以知道,这是xml验证模式的标志符,看看上面写的DTD和XSD大概就知道这几个变量的作用了。

    	/**
    	 * Indicates that the validation should be disabled.
    	 */
    	//无检验
    	public static final int VALIDATION_NONE = XmlValidationModeDetector.VALIDATION_NONE;
    
    	/**
    	 * Indicates that the validation mode should be detected automatically.
    	 */
    	//自动检测XML的检验模式
    	public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;
    
    	/**
    	 * Indicates that DTD validation should be used.
    	 */
    	//用DTD去进行校验
    	public static final int VALIDATION_DTD = XmlValidationModeDetector.VALIDATION_DTD;
    
    	/**
    	 * Indicates that XSD validation should be used.
    	 */
        //用XSD去进行校验
    	public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;
    	//默认自动检测
    	private int validationMode = VALIDATION_AUTO;
    	//XML校验模式侦查器
    	private final XmlValidationModeDetector validationModeDetector = new XmlValidationModeDetector();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    loadBeanDefinitions(Resource resource)

    实现BeanDefinitionReader接口的重要方法

    //这里是实现BeanDefinitionReader接口的重要方法
    	@Override
    	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    		return loadBeanDefinitions(new EncodedResource(resource));
    	}
    
    	//loadBeanDefinitions具体的实现方法
    	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    		Assert.notNull(encodedResource, "EncodedResource must not be null");
    		if (logger.isTraceEnabled()) {
    			logger.trace("Loading XML bean definitions from " + encodedResource);
    		}
    		//已经加载的Resource
    		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    		//判断是否重复加载
    		if (!currentResources.add(encodedResource)) {
    			throw new BeanDefinitionStoreException(
    					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    		}
    	
    		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
                //封装成org.xml.sax.InputSource(xml的输入源)
    			InputSource inputSource = new InputSource(inputStream);
    			if (encodedResource.getEncoding() != null) {
    				inputSource.setEncoding(encodedResource.getEncoding());
    			}
                //实际加载方法
    			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    		}
    		catch (IOException ex) {
    			throw new BeanDefinitionStoreException(
    					"IOException parsing XML document from " + encodedResource.getResource(), ex);
    		}
    		finally {
    			currentResources.remove(encodedResource);
    			if (currentResources.isEmpty()) {
    				this.resourcesCurrentlyBeingLoaded.remove();
    			}
    		}
    	}
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    doLoadBeanDefinitions(InputSource inputSource, Resource resource)

    加载BeanDefinitions的实际方法。

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    			throws BeanDefinitionStoreException {
    
    		try {
                //读取文件转成org.w3c.dom.Document(DOM树)
    			Document doc = doLoadDocument(inputSource, resource);
                //注册BeanDefinitions
    			int count = registerBeanDefinitions(doc, resource);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Loaded " + count + " bean definitions from " + resource);
    			}
    			return count;
    		}
    		//省去又臭又长的catch.....
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    registerBeanDefinitions(Document doc, Resource resource)

    虽然这里并不能直接告诉你BeanDefinitionDocumentReader怎么读取DOC中的bean,然后注册到IOC容器中的(因为做了很多层的封装,这里展开来读的话,已经脱离XmlBeanDefinitionReader的功能范围了)。最后还是会通过getRegistry()方法拿到Registry属性然后注册BeanDefinition

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            //创建BeanDefinitionDocumentReader(专门读取DOM树解析成BeanDefinition的类)
    		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        
        	//getRegistry()获取IOC容器(如:BeanFactory,Application)
            //这里获取加载前数量
    		int countBefore = getRegistry().getBeanDefinitionCount();
        
            //这里个方法做了很多doc的解析,最终会将BeanDefinitions加入到IOC容器中
    		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
            //返回加载数量
    		return getRegistry().getBeanDefinitionCount() - countBefore;
    	}
    
    
    //这里读一下上面的createReaderContext(resource)方法
    public XmlReaderContext createReaderContext(Resource resource) {
        //这里传了个this,所以XmlReaderContext是里面是可以拿到IOC容器的
    		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
    				this.sourceExtractor, this, getNamespaceHandlerResolver());
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    最终分析

    loadBeanDefinitions(Resource resource)最终会完成一下这些步骤:

    • 判断Resource是否重复加载,并且获取输入流
    • 从输入流中读取数据并生成DOM树(document对象)
      ceExtractor, this, getNamespaceHandlerResolver());
      }
  • 相关阅读:
    Ambari升级Atlas1.1.0到2.2.0
    TiDB Data Migration 快速上手指南
    【Linux】七、基础IO
    《论文阅读》R-NET: MACHINE READING COMPREHENSION WITH SELF-MATCHING NETWORKS
    一些事宜记录
    【译】使用.NET将WebAssembly扩展到云(一)
    银行排号叫号管理系统(MyEclipse+Java+GUI+MySQL)
    公司 CTO:高性能开发,你不会 Netty,怎么好意思拿 20K?
    Java 变量之变量数据类型
    数据可视化分析之新技能——魔数图
  • 原文地址:https://blog.csdn.net/qq_43203949/article/details/125470601