注:SpringFramework的版本是4.3.x。java
圖1 DispatchServlet的類繼承圖web
調用Servlet的init方法初始化Servlet,時序圖以下所示:spring
圖2 調用Servlet的init的時序圖app
這個init(...)是Servlet的方法,在容器container初始化Servlet時調會調用Servlet的init(...)方法。DispatcherServlet中經過init(...)來生成須要的webApplicationContext。ide
圖2中步驟6中的onRefresh(...)的實如今DispatcherServlet中實現,源碼以下List-1所示,initStrategies方法中對DispatcherServlet的屬性進行了初始化。學習
List-1 DispatcherServlet的onRefresh方法中的源碼this
@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); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
着重來看下方法initHandlerMappings的實現,方法中的源碼以下List-2所示spa
List-2 initHandlerMappings方法的源碼debug
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. 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) { this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default"); } } }
對LIst-2的說明:code
來分析getDefaultStrategies的源碼,以下List-3所示。
List-3 getDefaultStrategies的源碼
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) { String key = strategyInterface.getName(); 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()); 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>(); } }
defaultStrategies是DispatcherServlet的一個屬性,它的初始化以下List-4所示,
List-4 defaultStrategies的初始化源碼
private static final Properties defaultStrategies; 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 '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage()); } }
DEFAULT_STRATEGIES_PATH的值是DispatcherServlet.properties,咱們來看下這個文件裏面的內容,以下圖3所示,能夠看到默認狀況下HandlerMapping定義了倆個,即BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping,因此List-3中的createDefaultStrategy方法會將BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping建立爲bean,並註冊到applicationContext中。
圖3 文件DispatcherServlet.properties的內容
List-3中的createDefaultStrategy(context, clazz),代碼以下List-4所示。經過ApplicationContext和Class<?>,就能夠建立bean了,這種手動建立的方式能夠學習下。
List-4 方法createDefaultStrategy的源碼
protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) { return context.getAutowireCapableBeanFactory().createBean(clazz); }