1. 调用链
- 调用
ContextLoadListenner.initWebApplicationContext()
; - 调用
ContextLoadListenner.createWebApplicationContext()
:根据web.xml里面的contextClass配置的参数名确定Context类,如果没有就使用默认的WebApplicationContext
,并创建这个类的实例wac,调用wac.refresh()
; - 调用
ContextLoadListenner.configureAndRefreshWebApplicationContext()
: 根据web.xml配置的contextConfigLocation参数 确定配置文件位置 - 调用
wac.refresh()
: - 调用
wac.obtainFreshBeanFactory()
; - 调用
wac.refreshBeanFactory()
- 调用
wac.loadBeanDefinitions(beanFactory)
:创建XmlBeanDefinitionReader reader - 调用
reader.loadBeanDefinitions(configLocation)
:确定文件存在并创建IO流
public int loadBeanDefinitions(EncodedResource encodedResource) {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
}
- 调用
reader.doLoadBeanDefinitions()
:构造docreader 解析xml
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
- 调用
reader.registerBeanDefinitions()
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
- 调用
documentReader.registerBeanDefinition
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();//其实就是beans标签
doRegisterBeanDefinitions(root);
}
12 . 简化的代码
protected void doRegisterBeanDefinitions(Element root) {
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);//上下两个方法调用都是空实现,没用
postProcessXml(root);
}
- 真的加载逻辑
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();//xml doc 对象
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)) {
parseDefaultElement(ele, delegate);
}else {
delegate.parseCustomElement(ele);
}
}
}
}else {
delegate.parseCustomElement(root);
}
}
- xml标签tag标签解析
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
- 从缓存的数据寻找对应namespace的URI对应的
NameSpcaeHandler
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 {
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);// 创建handler对象
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);
}
}
}
- 这一步骤原理在ClassLoader.getResources(String location)加载所有jar里面的spring.handlers 这个文件里的配置
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;
}
2. NameSpcaceHandler加载逻辑简化
- ContextLoaderListener初始化
- 设置配置文件路径
- 生成DefaultBeanDefinitionDocumentReader实例 reader
- reader 解析配置xml,解析出根据标签的namespace 对应的URL
- 利用ClassLoader.getResource()加载全部的/META-INF/spring.handlers的配置
- 根据URL 查找 对应的NameSpaceHandler并初始化;