Spring 的NamSpaceHandlerResolverjava
一、此時的spring 已經獲取到了ResourceLoader獲取的File,建立了Document對象,spring
接下來進一步建立了DefaultBeanDefinitionDocumentReader對象的registerBeanDefinitions來解析註冊xml屬性express
此時該方法須要apache
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); }
public XmlReaderContext createReaderContext(Resource resource) { return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, getNamespaceHandlerResolver()); }
/*
* Copyright 2002-2007 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.parsing;
import org.springframework.core.io.Resource;
/**
* Context that gets passed along a bean definition reading process,
* encapsulating all relevant configuration as well as state.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 2.0
*/
public class ReaderContext {
private final Resource resource;
private final ProblemReporter problemReporter;
private final ReaderEventListener eventListener;
private final SourceExtractor sourceExtractor;
public ReaderContext(Resource resource, ProblemReporter problemReporter,
ReaderEventListener eventListener, SourceExtractor sourceExtractor) {
this.resource = resource;
this.problemReporter = problemReporter;
this.eventListener = eventListener;
this.sourceExtractor = sourceExtractor;
}
public final Resource getResource() {
return this.resource;
}
//---------------------------------------
//----------處理解析異常,如xml某行非法字符或者元素名稱不對---------
public void fatal(String message, Object source) {
fatal(message, source, null, null);
}
public void fatal(String message, Object source, Throwable ex) {
fatal(message, source, null, ex);
}
public void fatal(String message, Object source, ParseState parseState) {
fatal(message, source, parseState, null);
}
public void fatal(String message, Object source, ParseState parseState, Throwable cause) {
Location location = new Location(getResource(), source);
this.problemReporter.fatal(new Problem(message, location, parseState, cause));
}
public void error(String message, Object source) {
error(message, source, null, null);
}
public void error(String message, Object source, Throwable ex) {
error(message, source, null, ex);
}
public void error(String message, Object source, ParseState parseState) {
error(message, source, parseState, null);
}
public void error(String message, Object source, ParseState parseState, Throwable cause) {
Location location = new Location(getResource(), source);
this.problemReporter.error(new Problem(message, location, parseState, cause));
}
public void warning(String message, Object source) {
warning(message, source, null, null);
}
public void warning(String message, Object source, Throwable ex) {
warning(message, source, null, ex);
}
public void warning(String message, Object source, ParseState parseState) {
warning(message, source, parseState, null);
}
public void warning(String message, Object source, ParseState parseState, Throwable cause) {
Location location = new Location(getResource(), source);
this.problemReporter.warning(new Problem(message, location, parseState, cause));
}
//-------------------------------
//-----------向註冊的監聽發出事件
public void fireDefaultsRegistered(DefaultsDefinition defaultsDefinition) {
this.eventListener.defaultsRegistered(defaultsDefinition);
}
public void fireComponentRegistered(ComponentDefinition componentDefinition) {
this.eventListener.componentRegistered(componentDefinition);
}
public void fireAliasRegistered(String beanName, String alias, Object source) {
this.eventListener.aliasRegistered(new AliasDefinition(beanName, alias, source));
}
public void fireImportProcessed(String importedResource, Object source) {
this.eventListener.importProcessed(new ImportDefinition(importedResource, source));
}
public void fireImportProcessed(String importedResource, Resource[] actualResources, Object source) {
this.eventListener.importProcessed(new ImportDefinition(importedResource, actualResources, source));
}
public SourceExtractor getSourceExtractor() {
return this.sourceExtractor;
}
public Object extractSource(Object sourceCandidate) {
return this.sourceExtractor.extractSource(sourceCandidate, this.resource);
}
}
子類XmlReaderContext:app
/*
* Copyright 2002-2014 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.StringReader;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.parsing.ReaderContext;
import org.springframework.beans.factory.parsing.ReaderEventListener;
import org.springframework.beans.factory.parsing.SourceExtractor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
/**
* Extension of {@link org.springframework.beans.factory.parsing.ReaderContext},
* specific to use with an {@link XmlBeanDefinitionReader}. Provides access to the
* {@link NamespaceHandlerResolver} configured in the {@link XmlBeanDefinitionReader}.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 2.0
*/
public class XmlReaderContext extends ReaderContext {
private final XmlBeanDefinitionReader reader;
//此類是處理Xml的xsd空間解析的處理相應的xml定義元素,xml核心的處理對象
private final NamespaceHandlerResolver namespaceHandlerResolver;
public XmlReaderContext(
Resource resource, ProblemReporter problemReporter,
ReaderEventListener eventListener, SourceExtractor sourceExtractor,
XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {
super(resource, problemReporter, eventListener, sourceExtractor);
this.reader = reader;
this.namespaceHandlerResolver = namespaceHandlerResolver;
}
public final XmlBeanDefinitionReader getReader() {
return this.reader;
}
public final BeanDefinitionRegistry getRegistry() {
return this.reader.getRegistry();
}
public final ResourceLoader getResourceLoader() {
return this.reader.getResourceLoader();
}
public final ClassLoader getBeanClassLoader() {
return this.reader.getBeanClassLoader();
}
public final Environment getEnvironment() {
return this.reader.getEnvironment();
}
public final NamespaceHandlerResolver getNamespaceHandlerResolver() {
return this.namespaceHandlerResolver;
}
public String generateBeanName(BeanDefinition beanDefinition) {
return this.reader.getBeanNameGenerator().generateBeanName(beanDefinition, getRegistry());
}
public String registerWithGeneratedName(BeanDefinition beanDefinition) {
String generatedName = generateBeanName(beanDefinition);
getRegistry().registerBeanDefinition(generatedName, beanDefinition);
return generatedName;
}
public Document readDocumentFromString(String documentContent) {
InputSource is = new InputSource(new StringReader(documentContent));
try {
return this.reader.doLoadDocument(is, getResource());
}
catch (Exception ex) {
throw new BeanDefinitionStoreException("Failed to read XML document", ex);
}
}
}
/** * Lazily create a default NamespaceHandlerResolver, if not set before. * @see #createDefaultNamespaceHandlerResolver() */ public NamespaceHandlerResolver getNamespaceHandlerResolver() { if (this.namespaceHandlerResolver == null) { this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } return 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()); }
此時XmlBeanDefinittionReader建立的是DefaultNamespaceHandlerResolver對象less
/* * Copyright 2002-2012 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; /** * Default implementation of the {@link NamespaceHandlerResolver} interface. * Resolves namespace URIs to implementation classes based on the mappings * contained in mapping file. *查找xml的namespace url對應的對象的handler對象 * <p>By default, this implementation looks for the mapping file at * {@code META-INF/spring.handlers}, but this can be changed using the * {@link #DefaultNamespaceHandlerResolver(ClassLoader, String)} constructor. * 默認的handler對象在META-INF/spring.handlers文件裏面定義,次文件以下定義handler
http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
* @author Rob Harrop * @author Juergen Hoeller * @since 2.0 * @see NamespaceHandler * @see DefaultBeanDefinitionDocumentReader */ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver { /** * The location to look for the mapping files. Can be present in multiple JAR files. */ public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers"; /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); /** ClassLoader to use for NamespaceHandler classes */ private final ClassLoader classLoader; /** Resource location to search for */ private final String handlerMappingsLocation; /** Stores the mappings from namespace URI to NamespaceHandler class name / instance */ private volatile Map<String, Object> handlerMappings; /** * Create a new {@code DefaultNamespaceHandlerResolver} using the * default mapping file location. * <p>This constructor will result in the thread context ClassLoader being used * to load resources. * @see #DEFAULT_HANDLER_MAPPINGS_LOCATION */ public DefaultNamespaceHandlerResolver() { this(null, DEFAULT_HANDLER_MAPPINGS_LOCATION); } /** * Create a new {@code DefaultNamespaceHandlerResolver} using the * default mapping file location. * @param classLoader the {@link ClassLoader} instance used to load mapping resources * (may be {@code null}, in which case the thread context ClassLoader will be used) * @see #DEFAULT_HANDLER_MAPPINGS_LOCATION */ public DefaultNamespaceHandlerResolver(ClassLoader classLoader) { this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); } /** * Create a new {@code DefaultNamespaceHandlerResolver} using the * supplied mapping file location. * @param classLoader the {@link ClassLoader} instance used to load mapping resources * may be {@code null}, in which case the thread context ClassLoader will be used) * @param handlerMappingsLocation the mapping file location */ public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) { Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null"); this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); this.handlerMappingsLocation = handlerMappingsLocation; } /** * Locate the {@link NamespaceHandler} for the supplied namespace URI * from the configured mappings. * @param namespaceUri the relevant namespace URI * @return the located {@link NamespaceHandler}, or {@code null} if none found * 根據namespaceUri找到對應的handler對象 */ @Override public NamespaceHandler resolve(String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { //若是不是NamespaceHandler子類的handler則會拋出異常 String className = (String) handlerOrClassName; try { Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", ex); } catch (LinkageError err) { throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", err); } } } /** * Load the specified NamespaceHandler mappings lazily. * 獲取相應handler 根據handlerMappingsLocation 讀取META-INF/spring.handlers中的內容返回一個map */ private Map<String, Object> getHandlerMappings() { if (this.handlerMappings == null) { synchronized (this) { if (this.handlerMappings == null) { try { //讀取默認的 Properties mappings = PropertiesLoaderUtils.loadAllProperties (this.handlerMappingsLocation, this.classLoader); if (logger.isDebugEnabled()) { logger.debug("Loaded NamespaceHandler mappings: " + mappings); } Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size()); CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); this.handlerMappings = handlerMappings; } catch (IOException ex) { throw new IllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); } } } } return this.handlerMappings; } @Override public String toString() { return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); } }
至此處獲得了XmlReaderContextdom
到了註冊ide
protected void doRegisterBeanDefinitions(Element root) { // Any nested <beans> elements will cause recursion in this method. In // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); 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)) { return; } } } preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; } protected BeanDefinitionParserDelegate createDelegate( XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) { BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext); delegate.initDefaults(root, parentDelegate); return delegate; }
到建立真正的解析Document對象的解析類post
BeanDefinitionParserDelegateui