Spring源码学习(二)容器的基本实现

今天 圣诞节的次日 某汉的天气不错 加油 加油🦆
但晚上孝感地震 这里也有震感 希望大家都能平平安安

容器的基础 XmlBeanFactory

着重看一下这个代码的实现

		String path= "spring-config.xml";
		BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(path));

  • 了解XSD与DTD的区别,重点看文件头是否包含DOCTYPE
  • xsd
<?xml version="1.0" encoding="UTF-8"?>
<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>
  • dtd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>

</beans>
  • 了解EntityResolve,如上XSD/DTD中
  • 了解profile属性
  • 作用是配置两套配置,更方便的进行切换生产环境和开发环境
//在web.xml中
       <context-param>
		<param-name>Spring.profle.active</param-name>
		<param-value>dev</param-value>
	</context-param>

配置文件封装

  • 进入XmlBeanFactory()
       public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
	}
	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}
  • 从进入super(parentBeanFactory);再进入super()
	public AbstractAutowireCapableBeanFactory() {
		super();

		//ignoreDependencyInterface()功能:忽略给定接口的自动装配功能
		//eg:当A中有属性B,当Spring在获取A的bean的时候,如果B还没有初始化,那么Spring会自动初始化B
		//某些情况下B不会自动初始化,其中一种就是B实现了BeanNameAware接口
		//自动装配时忽略给定的依赖接口,典型的应用是通过其他方式解析Application上下文注册依赖,
		// 类似于BeanFactory通过BeanFactoryAware进行注入或者ApplicationContext通过ApplicationContextAware进行注入

		ignoreDependencyInterface(BeanNameAware.class);
		ignoreDependencyInterface(BeanFactoryAware.class);
		ignoreDependencyInterface(BeanClassLoaderAware.class);
	}
  • ignoreDependencyInterface用法详见以下链接

https://www.cnblogs.com/VVII/p/12109072.html

  • 进入this.reader.loadBeanDefinitions(resource);
	@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
                //new EncodedResource(resource) 主要对编码进行处理,后续会用到
		return loadBeanDefinitions(new EncodedResource(resource));
	}
	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		//先去掉一些不大重要的
                  ···
		  ···
		try {
			//从封装好的encodedResource中获取Resource并获取其InputStream
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				//org.xml.sax.InputSource
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//核心
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
  • 进入doLoadBeanDefinitions(inputSource, encodedResource.getResource());
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			//加载XML文件,获取对于的Document
			Document doc = doLoadDocument(inputSource, resource);
			//根据返回的doc注册Bean信息
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}

		············

	}
  • 获取验证模式
	protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
		return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
				getValidationModeForResource(resource), isNamespaceAware());
	}

	protected int getValidationModeForResource(Resource resource) {
		int validationModeToUse = getValidationMode();
		//手动指定了验证模式,就使用指定的验证模式
		if (validationModeToUse != VALIDATION_AUTO) {
			return validationModeToUse;
		}
		// 未指定则使用自动检测到的
		int detectedMode = detectValidationMode(resource);
		if (detectedMode != VALIDATION_AUTO) {
			return detectedMode;
		}
		return VALIDATION_XSD;
	}
  • 如何判别DTD与XSD
public int detectValidationMode(InputStream inputStream) throws IOException {
		// Peek into the file to look for DOCTYPE.
		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		try {
			boolean isDtdValidated = false;
			String content;
			while ((content = reader.readLine()) != null) {
				content = consumeCommentTokens(content);
				if (this.inComment || !StringUtils.hasText(content)) {
					continue;
				}
				// 包含DOCTYPE  则是DTD
				if (hasDoctype(content)) {
					isDtdValidated = true;
					break;
				}

				// 读取到<开始符号,验证模式一定会在开始符号之前
				if (hasOpeningTag(content)) {
					// End of meaningful data...
					break;
				}
			}
			// 包含"DOCTYPE"  则是DTD,否则就是XSD,Spring是这样判别的
			return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
		}
		catch (CharConversionException ex) {
			// Choked on some character encoding...
			// Leave the decision up to the caller.
			return VALIDATION_AUTO;
		}
		finally {
			reader.close();
		}
	}
  • EntityResolver

	protected EntityResolver getEntityResolver() {
		if (this.entityResolver == null) {
			// Determine default EntityResolver to use.
			ResourceLoader resourceLoader = getResourceLoader();
			if (resourceLoader != null) {
				this.entityResolver = new ResourceEntityResolver(resourceLoader);
			}
			else {
				this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
			}
		}
		return this.entityResolver;
	}
      //BeansDtdResolver
       @Override
	@Nullable
	public InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId) throws IOException {
		if (logger.isTraceEnabled()) {
			logger.trace("Trying to resolve XML entity with public ID [" + publicId +
					"] and system ID [" + systemId + "]");
		}

		if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
			int lastPathSeparator = systemId.lastIndexOf('/');
			int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);
			if (dtdNameStart != -1) {
				String dtdFile = DTD_NAME + DTD_EXTENSION;
				if (logger.isTraceEnabled()) {
					logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");
				}
				try {
					Resource resource = new ClassPathResource(dtdFile, getClass());
					InputSource source = new InputSource(resource.getInputStream());
					source.setPublicId(publicId);
					source.setSystemId(systemId);
					if (logger.isTraceEnabled()) {
						logger.trace("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
					}
					return source;
				}
				catch (FileNotFoundException ex) {
					if (logger.isDebugEnabled()) {
						logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
					}
				}
			}
		}

		// Fall back to the parser's default behavior.
		return null;
	}
         //DelegatingEntityResolver
	@Override
	@Nullable
	public InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId)
			throws SAXException, IOException {

		if (systemId != null) {
			if (systemId.endsWith(DTD_SUFFIX)) {
				return this.dtdResolver.resolveEntity(publicId, systemId);
			}
			else if (systemId.endsWith(XSD_SUFFIX)) {
				return this.schemaResolver.resolveEntity(publicId, systemId);
			}
		}

		// Fall back to the parser's default behavior.
		return null;
	}
  • 获取Document
	@Override
	public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
			ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

		DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
		if (logger.isTraceEnabled()) {
			logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
		}
		DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
		return builder.parse(inputSource);
	}
  • 解析并注册Definitions
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {

		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//getRegistry()  :返回BeanDefinitionRegistry
		// countBefore :记录统计前BeanDefinition的个数
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
  • 从 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));进入
	protected void doRegisterBeanDefinitions(Element root) {
		
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);


		···················

		// 空方法,留给子类实现
		preProcessXml(root);
		//
		parseBeanDefinitions(root, this.delegate);
		// 空方法,留给子类实现
		postProcessXml(root);

		this.delegate = parent;
	}
  • 进入parseBeanDefinitions()
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						// 对于默认的bean解析
						parseDefaultElement(ele, delegate);
					}
					else {
						// 对于自定义的bean解析
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			// 对于自定义的bean解析
			delegate.parseCustomElement(root);
		}
	}
posted @ 2019-12-26 21:38  VVII  阅读(166)  评论(0)    收藏  举报