2.2、spring之xml文件轉換爲BeanDefinition

一 、過程

1.1 根據schema獲取對應的處理器

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      ">
    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven/>
</beans>

在上面的時候我們使用了mvc的schema,那麼對於spring,是由哪個類來處理這個schema的呢?又是根據什麼來查找到這個對應的處理類呢?

我們知道mvc的schema是由MvcNamespaceHandler這個類進行處理的。那麼spring是如何將mvc的schema映射到對應的處理類的呢。

在這裏插入圖片描述
在spring 中存在一個NamespaceHandlerResolver接口,只有一個方法,根據schema來解析到對應的處理器。同時有一個默認的實現類。我們來看一下默認的實現類。

public NamespaceHandler resolve(String namespaceUri) {
        // 1、獲取所有的映射
		Map<String, Object> handlerMappings = getHandlerMappings();
		// 獲取映射對應的類名稱
		Object handlerOrClassName = handlerMappings.get(namespaceUri);
		if (handlerOrClassName == null) {
			return null;
		}
		else if (handlerOrClassName instanceof NamespaceHandler) {
		    // 2、如果類是NamespaceHandler的實現類,直接返回
			return (NamespaceHandler) handlerOrClassName;
		}
		else {
		     // 3、根據類名稱實例化NamespaceHandler的類,並存儲到映射的map。
			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);
			}
		}
	}

從中我們可以看到最重要的方法是getHandlerMappings();深入到該方法中

    if (this.handlerMappings == null) {
			synchronized (this) {
				if (this.handlerMappings == null) {
					try {
					   // 1、載入所有的Properties
						Properties mappings =
								PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
						if (logger.isDebugEnabled()) {
							logger.debug("Loaded NamespaceHandler mappings: " + mappings);
						}
						// 2、將Properties合併爲Map
						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;

我們看一下載入的時候handlerMappingsLocation的值。

public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";

由此,我們確定到xml的schema和對schema的映射關係是寫死在spring.handlers文件中的。我們可以再看一下spring.handlers文件中是如何進行存儲的。

http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler

現在我們確定了schema和處理器的關係,那麼處理器又是如何對schema中的內容進行處理的呢?

1.2 處理器處理信息

在這裏插入圖片描述
對於NamespaceHandler,我們可以看到有三個方法,初始化、解析元素信息、包裝信息。init()方法在類初始化後被調用(參考上方對於Handler的查找和初始化)。

public class MvcNamespaceHandler extends NamespaceHandlerSupport {

	public void init() {
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
		registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
		registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
		registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
	}

}

我們可以看一下對於mvc的handler處理器。可以看到建立了一級元素和Parser的映射關係。那麼我們可以看一下Parser的處理,Parser是對xml的硬編碼解析。

1.3 硬編碼解析xml文件


對於BeanDefinitionParser接口,只有一個方法parse,返回信息爲BeanDefinition。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章