Spring-mvc源碼分析之handlerMappings初始化

在分析spring源碼的時候,咱們知道handlerMapping是springMvc的一個組件,他的做用就是經過HandlerMapping找到具體Controller的具體類。那麼初始化的時候在DispatcherServlet中handlerMappings是怎麼初始化的呢?java

一、咱們知道在SpringMvc容器初始化的時候他會執行onRefresh方法web

//--DispatcherServlet類中的onRefresh方法
@Override
protected void onRefresh(ApplicationContext context) {
    //這裏會完成一些組件的初始化
	initStrategies(context);
}
/**
 * Initialize the strategy objects that this servlet uses.
 * <p>May be overridden in subclasses in order to initialize further strategy objects.
 */
protected void initStrategies(ApplicationContext context) {
	initMultipartResolver(context);
	initLocaleResolver(context);
	initThemeResolver(context);
	//這裏咱們主要關注一下HandlerMappings的初始化
	initHandlerMappings(context);
	initHandlerAdapters(context);
	initHandlerExceptionResolvers(context);
	initRequestToViewNameTranslator(context);
	initViewResolvers(context);
	initFlashMapManager(context);
}

那咱們看看initHandlerMappings(context)究竟是怎麼初始化的呢?spring

【DispatcherServlet.java】

/** Detect all HandlerMappings or just expect "handlerMapping" bean? */
private boolean detectAllHandlerMappings = true;
/**
 * Initialize the HandlerMappings used by this class.
 * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
 * we default to BeanNameUrlHandlerMapping.
 */
private void initHandlerMappings(ApplicationContext context) {
	this.handlerMappings = null;
	//在DispatcherServlet中咱們看到detectAllHandlerMappings屬性默認值是true
	if (this.detectAllHandlerMappings) {
		// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
		//首先這裏會在SpringContext容器中去查找類型爲HandlerMapping的類。
		Map<String, HandlerMapping> matchingBeans =
				BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
		if (!matchingBeans.isEmpty()) {
			this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
			// We keep HandlerMappings in sorted order.
			AnnotationAwareOrderComparator.sort(this.handlerMappings);
		}
	}
	else {
		try {
			HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
			this.handlerMappings = Collections.singletonList(hm);
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Ignore, we'll add a default HandlerMapping later.
		}
	}

	// Ensure we have at least one HandlerMapping, by registering
	// a default HandlerMapping if no other mappings are found.
	if (this.handlerMappings == null) {
		//獲取默認的HandlerMapping#關鍵代碼在這裏
		this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
		if (logger.isDebugEnabled()) {
			logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
		}
	}
}

this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class)執行完畢後,返回了默認的HandlerMapping的初始化mvc

【DispatcherServlet.java】
//這裏是一個常量,咱們看到他定義了properties文件的加載路徑
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
private static final Properties defaultStrategies;
//這裏咱們看到在DispatcherServlet初始化的時候,執行了一句靜態語句塊代碼,這裏主要是完成defaultStrategies資源初始化的問題。而且屬性上面加了final和static也就是隻能被初始化一次且不能更改
static {
	// Load default strategy implementations from properties file.
	// This is currently strictly internal and not meant to be customized
	// by application developers.
	try {
		ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
		defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
	}
	catch (IOException ex) {
		throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
	}
}
--這裏有必要看一看DispatcherServlet.properties配置文件關於HandlerMapping的配置
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
   org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
經過配置文件咱們看到,關於HandlerMapping這裏定義了二個默認的實現類

//Return:BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping的實例
@SuppressWarnings("unchecked")
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
	//strategyInterface就是HandlerMapping.class
	//key的值爲org.springframework.web.servlet.HandlerMapping
	String key = strategyInterface.getName();
	//這裏經過key在properties中去查找默認的配置信息
	String value = defaultStrategies.getProperty(key);
	if (value != null) {
		String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
		List<T> strategies = new ArrayList<T>(classNames.length);
		for (String className : classNames) {
			try {
				Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
				//這裏就是一個類初始化的問題。經過ApplicationContext建立一個bean。也就是讓這個bean經過spring容器進行管理
				Object strategy = createDefaultStrategy(context, clazz);
				strategies.add((T) strategy);
			}
			catch (ClassNotFoundException ex) {
				throw new BeanInitializationException(
						"Could not find DispatcherServlet's default strategy class [" + className +
								"] for interface [" + key + "]", ex);
			}
			catch (LinkageError err) {
				throw new BeanInitializationException(
						"Error loading DispatcherServlet's default strategy class [" + className +
								"] for interface [" + key + "]: problem with class file or dependent class", err);
			}
		}
		return strategies;
	}
	else {
		return new LinkedList<T>();
	}
}
相關文章
相關標籤/搜索