前言java
本文轉自「天河聊技術」微信公衆號spring
接着上一篇文章的bean定義解析繼續api
正文微信
上一次解析到這個方法org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)這行代碼app
// 加載bean定義 return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
// 加載xml文檔 Document doc = doLoadDocument(inputSource, resource);
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception { return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, getValidationModeForResource(resource), isNamespaceAware()); }
isNamespaceAware() 返回XML解析器是否應該具備XML名稱空間dom
進入這個方法org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getValidationModeForResourceide
protected int getValidationModeForResource(Resource resource) { int validationModeToUse = getValidationMode(); if (validationModeToUse != VALIDATION_AUTO) { return validationModeToUse; } int detectedMode = detectValidationMode(resource); if (detectedMode != VALIDATION_AUTO) { return detectedMode; } // Hmm, we didn't get a clear indication... Let's assume XSD, // since apparently no DTD declaration has been found up until // detection stopped (before finding the document's root tag). // 若是沒有解析到xml驗證模式就採用XSD驗證 return VALIDATION_XSD; }
進入這一行的這個方法this
int detectedMode = detectValidationMode(resource);
protected int detectValidationMode(Resource resource) { if (resource.isOpen()) { throw new BeanDefinitionStoreException( "Passed-in Resource [" + resource + "] contains an open stream: " + "cannot determine validation mode automatically. Either pass in a Resource " + "that is able to create fresh streams, or explicitly specify the validationMode " + "on your XmlBeanDefinitionReader instance."); } InputStream inputStream; try { inputStream = resource.getInputStream(); } catch (IOException ex) { throw new BeanDefinitionStoreException( "Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " + "Did you attempt to load directly from a SAX InputSource without specifying the " + "validationMode on your XmlBeanDefinitionReader instance?", ex); } try { return this.validationModeDetector.detectValidationMode(inputStream); } catch (IOException ex) { throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: an error occurred whilst reading from the InputStream.", ex); } }
進入這一行的這個方法spa
return this.validationModeDetector.detectValidationMode(inputStream);
org.springframework.util.xml.XmlValidationModeDetector#detectValidationModedebug
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聲明 if (hasDoctype(content)) { isDtdValidated = true; break; } // 判斷文件是不是以xml標記開頭 if (hasOpeningTag(content)) { // End of meaningful data... break; } } // 若是找到了DOCTYPE聲明就啓用DTD驗證,若是沒有就啓用XSD驗證 return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
} catch (CharConversionException ex) { // Choked on some character encoding... // Leave the decision up to the caller. 異常spring就會去猜想一種解析類型去解析 return VALIDATION_AUTO; } finally { reader.close(); } }
返回到這個方法
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadDocument
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception { return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, getValidationModeForResource(resource), isNamespaceAware()); }
loadDocument()加載xmnl文檔,底層是java的api
返回到這個方法
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions
// 註冊bean定義 return registerBeanDefinitions(doc, resource);
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 建立bean定義閱讀器 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); // 註冊bean定義以前先建立XmlReaderContext documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
進入這行代碼
// 註冊bean定義以前先建立 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
進入這個方法
public XmlReaderContext createReaderContext(Resource resource) { return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, getNamespaceHandlerResolver()); }
public NamespaceHandlerResolver getNamespaceHandlerResolver() { if (this.namespaceHandlerResolver == null) { this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } return this.namespaceHandlerResolver; }
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); return new DefaultNamespaceHandlerResolver(cl); }
public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); }
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
能夠看到是從這個路徑下加載的spring.handlers
返回到這個方法
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions這一行代碼
// 註冊bean定義以前先建立 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
進入這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
@Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); // 獲取xml文檔根節點 Element root = doc.getDocumentElement(); // 從xml文件中解析bean定義 doRegisterBeanDefinitions(root); }
進入這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
// 加載bean定義 BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); // 若是根節點是命名空間 http://www.springframework.org/schema/beans if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); // 解析環境配置文件 if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } }
進入這個方法
protected BeanDefinitionParserDelegate createDelegate( XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) { // bean定義解析委託 BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext); // bean定義默認配置 delegate.initDefaults(root, parentDelegate); return delegate; }
進入這個方法
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#initDefaults(org.w3c.dom.Element, org.springframework.beans.factory.xml.BeanDefinitionParserDelegate)
public void initDefaults(Element root, @Nullable BeanDefinitionParserDelegate parent) { // 解析默認的bean定義解析配置 populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root); // 觸發默認的bean定義事件 this.readerContext.fireDefaultsRegistered(this.defaults); }
進入這個方法
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#populateDefaults
// 解析beans標籤 protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) { // 解析default標籤值 是不是default-lazy-init,默認值是false,父配置文件的屬性會覆蓋子配置文件的屬性 String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { // Potentially inherited from outer <beans> sections, otherwise falling back to false. lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE); } defaults.setLazyInit(lazyInit); // default-merge 是不是這個值,默認值是false String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE); if (DEFAULT_VALUE.equals(merge)) { // Potentially inherited from outer <beans> sections, otherwise falling back to false. merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE); } defaults.setMerge(merge); // default-autowire 是不是這個值,默認值是no String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE); if (DEFAULT_VALUE.equals(autowire)) { // Potentially inherited from outer <beans> sections, otherwise falling back to 'no'. autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE); } defaults.setAutowire(autowire); // default-autowire-candidate 是否最爲候選bean被自動注入 if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) { defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates()); } // default-init-method if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) { defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setInitMethod(parentDefaults.getInitMethod()); } // default-destroy-method if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) { defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setDestroyMethod(parentDefaults.getDestroyMethod()); } defaults.setSource(this.readerContext.extractSource(root)); }
返回到這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions這一行
// 解析環境配置文件 if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
下片文章繼續。
最後
本次介紹到這裏,以上內容僅供參考。