XmlBeanDefinitionReader学习解析--属性部分

因为我在研究Spring的IOC,不可避免的(我好幽默)要研究一下XmlBeanDefinitionReader,代码如下:

/*
 * Copyright 2002-2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.beans.factory.xml;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.parsing.EmptyReaderEventListener;
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
import org.springframework.beans.factory.parsing.NullSourceExtractor;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.parsing.ReaderEventListener;
import org.springframework.beans.factory.parsing.SourceExtractor;
import org.springframework.beans.factory.support.AbstractBeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.Constants;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.io.DescriptiveResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.util.Assert;
import org.springframework.util.xml.SimpleSaxErrorHandler;
import org.springframework.util.xml.XmlValidationModeDetector;
/**
 * Bean definition reader for XML bean definitions.
 * Delegates the actual XML document reading to an implementation
 * of the {@link BeanDefinitionDocumentReader} interface.
 *
 * <p>Typically applied to a
 * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
 * or a {@link org.springframework.context.support.GenericApplicationContext}.
 *
 * <p>This class loads a DOM document and applies the BeanDefinitionDocumentReader to it.
 * The document reader will register each bean definition with the given bean factory,
 * talking to the latter's implementation of the
 * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry} interface.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @author Chris Beams
 * @since 26.11.2003
 * @see #setDocumentReaderClass
 * @see BeanDefinitionDocumentReader
 * @see DefaultBeanDefinitionDocumentReader
 * @see BeanDefinitionRegistry
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory
 * @see org.springframework.context.support.GenericApplicationContext
 */
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
 /**
  * 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.
  */
 public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;
 /**
  * Indicates that DTD validation should be used.
  */
 public static final int VALIDATION_DTD = XmlValidationModeDetector.VALIDATION_DTD;
 /**
  * Indicates that XSD validation should be used.
  */
 public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;
 /** Constants instance for this class */
 private static final Constants constants = new Constants(XmlBeanDefinitionReader.class);
 private int validationMode = VALIDATION_AUTO;
 private boolean namespaceAware = false;
 private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
 private ProblemReporter problemReporter = new FailFastProblemReporter();
 private ReaderEventListener eventListener = new EmptyReaderEventListener();
 private SourceExtractor sourceExtractor = new NullSourceExtractor();
 private NamespaceHandlerResolver namespaceHandlerResolver;
 private DocumentLoader documentLoader = new DefaultDocumentLoader();
 private EntityResolver entityResolver;
 private ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger);
 private final XmlValidationModeDetector validationModeDetector = new XmlValidationModeDetector();
 private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
   new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");
 /**
  * Create new XmlBeanDefinitionReader for the given bean factory.
  * @param registry the BeanFactory to load bean definitions into,
  * in the form of a BeanDefinitionRegistry
  */
 public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
  super(registry);
 }
 /**
  * Set whether to use XML validation. Default is <code>true</code>.
  * <p>This method switches namespace awareness on if validation is turned off,
  * in order to still process schema namespaces properly in such a scenario.
  * @see #setValidationMode
  * @see #setNamespaceAware
  */
 public void setValidating(boolean validating) {
  this.validationMode = (validating ? VALIDATION_AUTO : VALIDATION_NONE);
  this.namespaceAware = !validating;
 }
 /**
  * Set the validation mode to use by name. Defaults to {@link #VALIDATION_AUTO}.
  * @see #setValidationMode
  */
 public void setValidationModeName(String validationModeName) {
  setValidationMode(constants.asNumber(validationModeName).intValue());
 }
 /**
  * Set the validation mode to use. Defaults to {@link #VALIDATION_AUTO}.
  * <p>Note that this only activates or deactivates validation itself.
  * If you are switching validation off for schema files, you might need to
  * activate schema namespace support explicitly: see {@link #setNamespaceAware}.
  */
 public void setValidationMode(int validationMode) {
  this.validationMode = validationMode;
 }
 /**
  * Return the validation mode to use.
  */
 public int getValidationMode() {
  return this.validationMode;
 }
 /**
  * Set whether or not the XML parser should be XML namespace aware.
  * Default is "false".
  * <p>This is typically not needed when schema validation is active.
  * However, without validation, this has to be switched to "true"
  * in order to properly process schema namespaces.
  */
 public void setNamespaceAware(boolean namespaceAware) {
  this.namespaceAware = namespaceAware;
 }
 /**
  * Return whether or not the XML parser should be XML namespace aware.
  */
 public boolean isNamespaceAware() {
  return this.namespaceAware;
 }
 /**
  * Specify which {@link org.springframework.beans.factory.parsing.ProblemReporter} to use.
  * <p>The default implementation is {@link org.springframework.beans.factory.parsing.FailFastProblemReporter}
  * which exhibits fail fast behaviour. External tools can provide an alternative implementation
  * that collates errors and warnings for display in the tool UI.
  */
 public void setProblemReporter(ProblemReporter problemReporter) {
  this.problemReporter = (problemReporter != null ? problemReporter : new FailFastProblemReporter());
 }
 /**
  * Specify which {@link ReaderEventListener} to use.
  * <p>The default implementation is EmptyReaderEventListener which discards every event notification.
  * External tools can provide an alternative implementation to monitor the components being
  * registered in the BeanFactory.
  */
 public void setEventListener(ReaderEventListener eventListener) {
  this.eventListener = (eventListener != null ? eventListener : new EmptyReaderEventListener());
 }
 /**
  * Specify the {@link SourceExtractor} to use.
  * <p>The default implementation is {@link NullSourceExtractor} which simply returns <code>null</code>
  * as the source object. This means that - during normal runtime execution -
  * no additional source metadata is attached to the bean configuration metadata.
  */
 public void setSourceExtractor(SourceExtractor sourceExtractor) {
  this.sourceExtractor = (sourceExtractor != null ? sourceExtractor : new NullSourceExtractor());
 }
 /**
  * Specify the {@link NamespaceHandlerResolver} to use.
  * <p>If none is specified, a default instance will be created through
  * {@link #createDefaultNamespaceHandlerResolver()}.
  */
 public void setNamespaceHandlerResolver(NamespaceHandlerResolver namespaceHandlerResolver) {
  this.namespaceHandlerResolver = namespaceHandlerResolver;
 }
 /**
  * Specify the {@link DocumentLoader} to use.
  * <p>The default implementation is {@link DefaultDocumentLoader}
  * which loads {@link Document} instances using JAXP.
  */
 public void setDocumentLoader(DocumentLoader documentLoader) {
  this.documentLoader = (documentLoader != null ? documentLoader : new DefaultDocumentLoader());
 }
 /**
  * Set a SAX entity resolver to be used for parsing.
  * <p>By default, {@link ResourceEntityResolver} will be used. Can be overridden
  * for custom entity resolution, for example relative to some specific base path.
  */
 public void setEntityResolver(EntityResolver entityResolver) {
  this.entityResolver = entityResolver;
 }
 /**
  * Return the EntityResolver to use, building a default resolver
  * if none specified.
  */
 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;
 }
 /**
  * Set an implementation of the <code>org.xml.sax.ErrorHandler</code>
  * interface for custom handling of XML parsing errors and warnings.
  * <p>If not set, a default SimpleSaxErrorHandler is used that simply
  * logs warnings using the logger instance of the view class,
  * and rethrows errors to discontinue the XML transformation.
  * @see SimpleSaxErrorHandler
  */
 public void setErrorHandler(ErrorHandler errorHandler) {
  this.errorHandler = errorHandler;
 }
 /**
  * Specify the {@link BeanDefinitionDocumentReader} implementation to use,
  * responsible for the actual reading of the XML bean definition document.
  * <p>The default is {@link DefaultBeanDefinitionDocumentReader}.
  * @param documentReaderClass the desired BeanDefinitionDocumentReader implementation class
  */
 public void setDocumentReaderClass(Class<?> documentReaderClass) {
  if (documentReaderClass == null || !BeanDefinitionDocumentReader.class.isAssignableFrom(documentReaderClass)) {
   throw new IllegalArgumentException(
     "documentReaderClass must be an implementation of the BeanDefinitionDocumentReader interface");
  }
  this.documentReaderClass = documentReaderClass;
 }
 /**
  * Load bean definitions from the specified XML file.
  * @param resource the resource descriptor for the XML file
  * @return the number of bean definitions found
  * @throws BeanDefinitionStoreException in case of loading or parsing errors
  */
 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
  return loadBeanDefinitions(new EncodedResource(resource));
 }
 /**
  * Load bean definitions from the specified XML file.
  * @param encodedResource the resource descriptor for the XML file,
  * allowing to specify an encoding to use for parsing the file
  * @return the number of bean definitions found
  * @throws BeanDefinitionStoreException in case of loading or parsing errors
  */
 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
  Assert.notNull(encodedResource, "EncodedResource must not be null");
  if (logger.isInfoEnabled()) {
   logger.info("Loading XML bean definitions from " + encodedResource.getResource());
  }
  Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
  if (currentResources == null) {
   currentResources = new HashSet<EncodedResource>(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 {
    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();
   }
  }
 }
 /**
  * Load bean definitions from the specified XML file.
  * @param inputSource the SAX InputSource to read from
  * @return the number of bean definitions found
  * @throws BeanDefinitionStoreException in case of loading or parsing errors
  */
 public int loadBeanDefinitions(InputSource inputSource) throws BeanDefinitionStoreException {
  return loadBeanDefinitions(inputSource, "resource loaded through SAX InputSource");
 }
 /**
  * Load bean definitions from the specified XML file.
  * @param inputSource the SAX InputSource to read from
  * @param resourceDescription a description of the resource
  * (can be <code>null</code> or empty)
  * @return the number of bean definitions found
  * @throws BeanDefinitionStoreException in case of loading or parsing errors
  */
 public int loadBeanDefinitions(InputSource inputSource, String resourceDescription)
   throws BeanDefinitionStoreException {
  return doLoadBeanDefinitions(inputSource, new DescriptiveResource(resourceDescription));
 }
 /**
  * Actually load bean definitions from the specified XML file.
  * @param inputSource the SAX InputSource to read from
  * @param resource the resource descriptor for the XML file
  * @return the number of bean definitions found
  * @throws BeanDefinitionStoreException in case of loading or parsing errors
  */
 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
   throws BeanDefinitionStoreException {
  try {
   int validationMode = getValidationModeForResource(resource);
   Document doc = this.documentLoader.loadDocument(
     inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
   return registerBeanDefinitions(doc, resource);
  }
  catch (BeanDefinitionStoreException ex) {
   throw ex;
  }
  catch (SAXParseException ex) {
   throw new XmlBeanDefinitionStoreException(resource.getDescription(),
     "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
  }
  catch (SAXException ex) {
   throw new XmlBeanDefinitionStoreException(resource.getDescription(),
     "XML document from " + resource + " is invalid", ex);
  }
  catch (ParserConfigurationException ex) {
   throw new BeanDefinitionStoreException(resource.getDescription(),
     "Parser configuration exception parsing XML from " + resource, ex);
  }
  catch (IOException ex) {
   throw new BeanDefinitionStoreException(resource.getDescription(),
     "IOException parsing XML document from " + resource, ex);
  }
  catch (Throwable ex) {
   throw new BeanDefinitionStoreException(resource.getDescription(),
     "Unexpected exception parsing XML document from " + resource, ex);
  }
 }
 /**
  * Gets the validation mode for the specified {@link Resource}. If no explicit
  * validation mode has been configured then the validation mode is
  * {@link #detectValidationMode detected}.
  * <p>Override this method if you would like full control over the validation
  * mode, even when something other than {@link #VALIDATION_AUTO} was set.
  */
 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).
  return VALIDATION_XSD;
 }
 /**
  * Detects which kind of validation to perform on the XML file identified
  * by the supplied {@link Resource}. If the file has a <code>DOCTYPE</code>
  * definition then DTD validation is used otherwise XSD validation is assumed.
  * <p>Override this method if you would like to customize resolution
  * of the {@link #VALIDATION_AUTO} mode.
  */
 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);
  }
 }
 /**
  * Register the bean definitions contained in the given DOM document.
  * Called by <code>loadBeanDefinitions</code>.
  * <p>Creates a new instance of the parser class and invokes
  * <code>registerBeanDefinitions</code> on it.
  * @param doc the DOM document
  * @param resource the resource descriptor (for context information)
  * @return the number of bean definitions found
  * @throws BeanDefinitionStoreException in case of parsing errors
  * @see #loadBeanDefinitions
  * @see #setDocumentReaderClass
  * @see BeanDefinitionDocumentReader#registerBeanDefinitions
  */
 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
  BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
  documentReader.setEnvironment(this.getEnvironment());
  int countBefore = getRegistry().getBeanDefinitionCount();
  documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
  return getRegistry().getBeanDefinitionCount() - countBefore;
 }
 /**
  * Create the {@link BeanDefinitionDocumentReader} to use for actually
  * reading bean definitions from an XML document.
  * <p>The default implementation instantiates the specified "documentReaderClass".
  * @see #setDocumentReaderClass
  */
 protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
  return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
 }
 /**
  * Create the {@link XmlReaderContext} to pass over to the document reader.
  */
 protected XmlReaderContext createReaderContext(Resource resource) {
  if (this.namespaceHandlerResolver == null) {
   this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
  }
  return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
    this.sourceExtractor, this, this.namespaceHandlerResolver);
 }
 /**
  * Create the default implementation of {@link NamespaceHandlerResolver} used if none is specified.
  * Default implementation returns an instance of {@link DefaultNamespaceHandlerResolver}.
  */
 protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
  return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
 }
}

首先我来看一下属性部分:

/**
  * 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.
  */
 public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;
 /**
  * Indicates that DTD validation should be used.
  */
 public static final int VALIDATION_DTD = XmlValidationModeDetector.VALIDATION_DTD;
 /**
  * Indicates that XSD validation should be used.
  */
 public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;
 /** Constants instance for this class */
 private static final Constants constants = new Constants(XmlBeanDefinitionReader.class);
 private int validationMode = VALIDATION_AUTO;
 private boolean namespaceAware = false;
 private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
 private ProblemReporter problemReporter = new FailFastProblemReporter();
 private ReaderEventListener eventListener = new EmptyReaderEventListener();
 private SourceExtractor sourceExtractor = new NullSourceExtractor();
 private NamespaceHandlerResolver namespaceHandlerResolver;
 private DocumentLoader documentLoader = new DefaultDocumentLoader();
 private EntityResolver entityResolver;
 private ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger);
 private final XmlValidationModeDetector validationModeDetector = new XmlValidationModeDetector();
 private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
   new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");

VALIDATION_NONE,表明验证应该禁用。

VALIDATION_AUTO,表明验证应该被自动检测到

VALIDATION_DTD,表明DTD验证应该被使用(关于DTD技术,这里躺着(我好幽默)一个链接http://blog.csdn.net/xiazdong/article/details/7270593

VALIDATION_XSD,表明XSD验证应该被使用(关于XSD技术,这里又躺着(我好幽默)一个链接

http://blog.csdn.net/evanerv0079/article/details/2515313

constants属性,是一个Constants,做什么用的呢?Constants构造函数如下:

 /**
  * Create a new Constants converter class wrapping the given class.
  * <p>All <b>public</b> static final variables will be exposed, whatever their type.
  * @param clazz the class to analyze
  * @throws IllegalArgumentException if the supplied <code>clazz</code> is <code>null</code>
  */
 public Constants(Class clazz) {
  Assert.notNull(clazz);
  this.className = clazz.getName();
  Field[] fields = clazz.getFields();
  for (Field field : fields) {
   if (ReflectionUtils.isPublicStaticFinal(field)) {
    String name = field.getName();
    try {
     Object value = field.get(null);
     this.fieldCache.put(name, value);
    }
    catch (IllegalAccessException ex) {
     // just leave this field and continue
    }
   }
  }
 }

看到了没,just leave this field and continue这句话写的真好,这个类主要就是用来包装类的静态属性,放入一个Map集合,然后随去随用,因为这个属性也同样是static final的。

validationMode:默认下使用自动扫描的验证模式。

namespaceAware:false,表明不去发现命名空间?不确定,以后修改

documentReaderClass:用了和ApplicationContext关联紧密的DefaultBeanDefinitionDocumentReader类,有点意思。

problemReporter,对快速失败问题的报告类。

package org.springframework.beans.factory.parsing;
/**
 * SPI interface allowing tools and other external processes to handle errors
 * and warnings reported during bean definition parsing.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @since 2.0
 * @see Problem
 */
public interface ProblemReporter {
 /**
  * Called when a fatal error is encountered during the parsing process.
  * <p>Implementations must treat the given problem as fatal,
  * i.e. they have to eventually raise an exception.
  * @param problem the source of the error (never <code>null</code>)
  */
 void fatal(Problem problem);
 /**
  * Called when an error is encountered during the parsing process.
  * <p>Implementations may choose to treat errors as fatal.
  * @param problem the source of the error (never <code>null</code>)
  */
 void error(Problem problem);
 /**
  * Called when a warning is raised during the parsing process.
  * <p>Warnings are <strong>never</strong> considered to be fatal.
  * @param problem the source of the warning (never <code>null</code>)
  */
 void warning(Problem problem);
}

源码表明对fetal(严重),error(错误),warning(警告)级别的错误信息分别处理生成报告。

eventListener:事件监听器,代码如下。

package org.springframework.beans.factory.parsing;
import java.util.EventListener;
/**
 * Interface that receives callbacks for component, alias and import
 * registrations during a bean definition reading process.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @since 2.0
 * @see ReaderContext
 */
public interface ReaderEventListener extends EventListener {
 /**
  * Notification that the given defaults has been registered.
  * @param defaultsDefinition a descriptor for the defaults
  * @see org.springframework.beans.factory.xml.DocumentDefaultsDefinition
  */
 void defaultsRegistered(DefaultsDefinition defaultsDefinition);
 /**
  * Notification that the given component has been registered.
  * @param componentDefinition a descriptor for the new component
  * @see BeanComponentDefinition
  */
 void componentRegistered(ComponentDefinition componentDefinition);
 /**
  * Notification that the given alias has been registered.
  * @param aliasDefinition a descriptor for the new alias
  */
 void aliasRegistered(AliasDefinition aliasDefinition);
 /**
  * Notification that the given import has been processed.
  * @param importDefinition a descriptor for the import
  */
 void importProcessed(ImportDefinition importDefinition);
}

针对不同的定义,进行事件的监听,四个事件,DefaultsDefinition,ComponentDefinition,AliasDefinition,ImportDefinition,具体的实现可以查看源代码。默认将EmptyReaderEventListener监听器给了这个属性(幽默)。

sourceExtractor:代码如下

package org.springframework.beans.factory.parsing;
import org.springframework.core.io.Resource;
/**
 * Simple strategy allowing tools to control how source metadata is attached
 * to the bean definition metadata.
 *
 * <p>Configuration parsers <strong>may</strong> provide the ability to attach
 * source metadata during the parse phase. They will offer this metadata in a
 * generic format which can be further modified by a {@link SourceExtractor}
 * before being attached to the bean definition metadata.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @since 2.0
 * @see org.springframework.beans.BeanMetadataElement#getSource()
 * @see org.springframework.beans.factory.config.BeanDefinition
 */
public interface SourceExtractor {
 /**
  * Extract the source metadata from the candidate object supplied
  * by the configuration parser.
  * @param sourceCandidate the original source metadata (never <code>null</code>)
  * @param definingResource the resource that defines the given source object
  * (may be <code>null</code>)
  * @return the source metadata object to store (may be <code>null</code>)
  */
 Object extractSource(Object sourceCandidate, Resource definingResource);
}

 Object extractSource(Object sourceCandidate, Resource definingResource);提取资源,通过的定的定义资源类型和投进去的资源。

namespaceHandlerResolver:NamespaceHandlerResolver类的一个属性名,用来解决命名空间的handler问题(白说),主要应该用来生成引用。

documentLoader:DocumentLoader类的属性名,用来加载document文档类型的source。

package org.springframework.beans.factory.xml;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
/**
 * Strategy interface for loading an XML {@link Document}.
 *
 * @author Rob Harrop
 * @since 2.0
 * @see DefaultDocumentLoader
 */
public interface DocumentLoader {
 /**
  * Load a {@link Document document} from the supplied {@link InputSource source}.
  * @param inputSource the source of the document that is to be loaded
  * @param entityResolver the resolver that is to be used to resolve any entities
  * @param errorHandler used to report any errors during document loading
  * @param validationMode the type of validation
  * {@link org.springframework.util.xml.XmlValidationModeDetector#VALIDATION_DTD DTD}
  * or {@link org.springframework.util.xml.XmlValidationModeDetector#VALIDATION_XSD XSD})
  * @param namespaceAware <code>true</code> if support for XML namespaces is to be provided
  * @return the loaded {@link Document document}
  * @throws Exception if an error occurs
  */
 Document loadDocument(
   InputSource inputSource, EntityResolver entityResolver,
   ErrorHandler errorHandler, int validationMode, boolean namespaceAware)
   throws Exception;
}

针对输入的Source,根据验证模式,是否命名空间说明,应用EntityResolver实体解决类加入ErrorHandler协助完成功能。

entityResolver:EntityResolver类的变量,针对上面一个属性已经用了它,暗示着这个EntityResolver只是一个蓝领工具类。

errorHandler:ErrorHandler类的变量,一样蓝领。

validationModeDetector:XmlValidationModeDetector类的变量,对xml验证模式的检测,是个很重要的属性哦!

 package org.springframework.util.xml;
import java.io.BufferedReader;
import java.io.CharConversionException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.util.StringUtils;
/**
 * Detects whether an XML stream is using DTD- or XSD-based validation.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @since 2.0
 */
public class XmlValidationModeDetector {
 /**
  * Indicates that the validation should be disabled.
  */
 public static final int VALIDATION_NONE = 0;
 /**
  * Indicates that the validation mode should be auto-guessed, since we cannot find
  * a clear indication (probably choked on some special characters, or the like).
  */
 public static final int VALIDATION_AUTO = 1;
 /**
  * Indicates that DTD validation should be used (we found a "DOCTYPE" declaration).
  */
 public static final int VALIDATION_DTD = 2;
 /**
  * Indicates that XSD validation should be used (found no "DOCTYPE" declaration).
  */
 public static final int VALIDATION_XSD = 3;

 /**
  * The token in a XML document that declares the DTD to use for validation
  * and thus that DTD validation is being used.
  */
 private static final String DOCTYPE = "DOCTYPE";
 /**
  * The token that indicates the start of an XML comment.
  */
 private static final String START_COMMENT = "<!--";
 /**
  * The token that indicates the end of an XML comment.
  */
 private static final String END_COMMENT = "-->";

 /**
  * Indicates whether or not the current parse position is inside an XML comment.
  */
 private boolean inComment;

 /**
  * Detect the validation mode for the XML document in the supplied {@link InputStream}.
  * Note that the supplied {@link InputStream} is closed by this method before returning.
  * @param inputStream the InputStream to parse
  * @throws IOException in case of I/O failure
  * @see #VALIDATION_DTD
  * @see #VALIDATION_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;
    }
    if (hasDoctype(content)) {
     isDtdValidated = true;
     break;
    }
    if (hasOpeningTag(content)) {
     // End of meaningful data...
     break;
    }
   }
   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();
  }
 }

 /**
  * Does the content contain the the DTD DOCTYPE declaration?
  */
 private boolean hasDoctype(String content) {
  return (content.indexOf(DOCTYPE) > -1);
 }
 /**
  * Does the supplied content contain an XML opening tag. If the parse state is currently
  * in an XML comment then this method always returns false. It is expected that all comment
  * tokens will have consumed for the supplied content before passing the remainder to this method.
  */
 private boolean hasOpeningTag(String content) {
  if (this.inComment) {
   return false;
  }
  int openTagIndex = content.indexOf('<');
  return (openTagIndex > -1 && content.length() > openTagIndex && Character.isLetter(content.charAt(openTagIndex + 1)));
 }
 /**
  * Consumes all the leading comment data in the given String and returns the remaining content, which
  * may be empty since the supplied content might be all comment data. For our purposes it is only important
  * to strip leading comment content on a line since the first piece of non comment content will be either
  * the DOCTYPE declaration or the root element of the document.
  */
 private String consumeCommentTokens(String line) {
  if (line.indexOf(START_COMMENT) == -1 && line.indexOf(END_COMMENT) == -1) {
   return line;
  }
  while ((line = consume(line)) != null) {
   if (!this.inComment && !line.trim().startsWith(START_COMMENT)) {
    return line;
   }
  }
  return line;
 }
 /**
  * Consume the next comment token, update the "inComment" flag
  * and return the remaining content.
  */
 private String consume(String line) {
  int index = (this.inComment ? endComment(line) : startComment(line));
  return (index == -1 ? null : line.substring(index));
 }
 /**
  * Try to consume the {@link #START_COMMENT} token.
  * @see #commentToken(String, String, boolean)
  */
 private int startComment(String line) {
  return commentToken(line, START_COMMENT, true);
 }
 private int endComment(String line) {
  return commentToken(line, END_COMMENT, false);
 }
 /**
  * Try to consume the supplied token against the supplied content and update the
  * in comment parse state to the supplied value. Returns the index into the content
  * which is after the token or -1 if the token is not found.
  */
 private int commentToken(String line, String token, boolean inCommentIfPresent) {
  int index = line.indexOf(token);
  if (index > - 1) {
   this.inComment = inCommentIfPresent;
  }
  return (index == -1 ? index : index + token.length());
 }
}

主要根据输入流在缓冲区中对输入流携带的Token进行分类处理。

resourcesCurrentlyBeingLoaded:ThreadLocal的一个变量,很有趣的一个泛型类,ThreadLocal<Set<EncodedResource>>预示着你可以存储任何类型在这个对象实例中,但如何使用还未知。

转载于:https://my.oschina.net/stuspring/blog/472592

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值