SpringMVC源码解读 - HandlerMapping - SimpleUrlHandlerMapping初始化
2016-02-22 17:45
656 查看
摘要:
SimpleUrlHandlerMapping只是参与Handler的注册,请求映射时由AbstractUrlHandlerMapping搞定.
初始化时,通过setMappings(Properties mappings)或者setUrlMap(Map<String, ?> urlMap)设置映射关系,然后通过WebApplicationObjectSupport的initApplicationContext调用registerHandlers进行注册.
覆写initApplicationContext方法时,先调用父类实现,然后才调用registerHandlers进行注册.其中最终的注册registerHandler实现是由AbstractUrlHandlerMapping实现的.
父类AbstractHandlerMapping继承了WebApplicationObjectSupport,所以SimpleUrlHandlerMapping可以通过覆写initApplicationContext注册Handler.
注册Handler前,不忘靠AbstractHandlerMapping来初始化拦截器.
// SimpleUrlHandlerMapping
initApplicationContext主要是进行拦截器的初始化.
extendInterceptors是留给子类用的扩展接口,暂时没有使用
detectMappedInterceptors是通过BeanFactoryUtils扫描应用下的全部MappedInterceptor类
initInterceptors初始化特定的拦截器,检查MappedInterceptor,在需要时适配adaptor HandlerInterceptor
// AbstractHandlerMapping
// AbstractHandlerMapping
springmvc中经常使用BeanFactoryUtils扫描应用下的类来进行初始化.
// AbstractHandlerMapping
// AbstractHandlerMapping
适配HandlerInterceptor和WebRequestHandlerInterceptorAdapter(什么是WebRequestHandlerInterceptorAdapter,晚点再说吧,具体看到时候拦截器部分的分析)
// AbstractHandlerMapping
这才到SimpleUrlHandlerMapping干活的地方,迭代urlMap调用AbstractUrlHandlerMapping的registerHandler进行注册
(保障url以"/"开头就不多说了)
// SimpleUrlHandlerMapping
// AbstractUrlHandlerMapping
SimpleUrlHandlerMapping只是参与Handler的注册,请求映射时由AbstractUrlHandlerMapping搞定.
初始化时,通过setMappings(Properties mappings)或者setUrlMap(Map<String, ?> urlMap)设置映射关系,然后通过WebApplicationObjectSupport的initApplicationContext调用registerHandlers进行注册.
覆写initApplicationContext方法时,先调用父类实现,然后才调用registerHandlers进行注册.其中最终的注册registerHandler实现是由AbstractUrlHandlerMapping实现的.
父类AbstractHandlerMapping继承了WebApplicationObjectSupport,所以SimpleUrlHandlerMapping可以通过覆写initApplicationContext注册Handler.
注册Handler前,不忘靠AbstractHandlerMapping来初始化拦截器.
// SimpleUrlHandlerMapping
/** * Calls the {@link #registerHandlers} method in addition to the * superclass's initialization. */ @Override public void initApplicationContext() throws BeansException { super.initApplicationContext(); registerHandlers(this.urlMap); }
initApplicationContext主要是进行拦截器的初始化.
extendInterceptors是留给子类用的扩展接口,暂时没有使用
detectMappedInterceptors是通过BeanFactoryUtils扫描应用下的全部MappedInterceptor类
initInterceptors初始化特定的拦截器,检查MappedInterceptor,在需要时适配adaptor HandlerInterceptor
// AbstractHandlerMapping
/** * Initializes the interceptors. * @see #extendInterceptors(java.util.List) * @see #initInterceptors() */ @Override protected void initApplicationContext() throws BeansException { extendInterceptors(this.interceptors); detectMappedInterceptors(this.mappedInterceptors); initInterceptors(); }
// AbstractHandlerMapping
/** * Extension hook that subclasses can override to register additional interceptors, * given the configured interceptors (see {@link #setInterceptors}). * <p>Will be invoked before {@link #initInterceptors()} adapts the specified * interceptors into {@link HandlerInterceptor} instances. * <p>The default implementation is empty. * @param interceptors the configured interceptor List (never {@code null}), * allowing to add further interceptors before as well as after the existing * interceptors */ protected void extendInterceptors(List<Object> interceptors) { }
springmvc中经常使用BeanFactoryUtils扫描应用下的类来进行初始化.
// AbstractHandlerMapping
/** * Detects beans of type {@link MappedInterceptor} and adds them to the list of mapped interceptors. * This is done in addition to any {@link MappedInterceptor}s that may have been provided via * {@link #setInterceptors(Object[])}. Subclasses can override this method to change that. * * @param mappedInterceptors an empty list to add MappedInterceptor types to */ protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) { mappedInterceptors.addAll( BeanFactoryUtils.beansOfTypeIncludingAncestors( getApplicationContext(),MappedInterceptor.class, true, false).values()); }
// AbstractHandlerMapping
/** * Initialize the specified interceptors, checking for {@link MappedInterceptor}s and adapting * HandlerInterceptors where necessary. * @see #setInterceptors * @see #adaptInterceptor */ protected void initInterceptors() { if (!this.interceptors.isEmpty()) { for (int i = 0; i < this.interceptors.size(); i++) { Object interceptor = this.interceptors.get(i); if (interceptor == null) { throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null"); } if (interceptor instanceof MappedInterceptor) { mappedInterceptors.add((MappedInterceptor) interceptor); } else { adaptedInterceptors.add(adaptInterceptor(interceptor)); } } } }
适配HandlerInterceptor和WebRequestHandlerInterceptorAdapter(什么是WebRequestHandlerInterceptorAdapter,晚点再说吧,具体看到时候拦截器部分的分析)
// AbstractHandlerMapping
/** * Adapt the given interceptor object to the HandlerInterceptor interface. * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor. * Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter. * Can be overridden in subclasses. * @param interceptor the specified interceptor object * @return the interceptor wrapped as HandlerInterceptor * @see org.springframework.web.servlet.HandlerInterceptor * @see org.springframework.web.context.request.WebRequestInterceptor * @see WebRequestHandlerInterceptorAdapter */ protected HandlerInterceptor adaptInterceptor(Object interceptor) { if (interceptor instanceof HandlerInterceptor) { return (HandlerInterceptor) interceptor; } else if (interceptor instanceof WebRequestInterceptor) { return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor); } else { throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName()); } }
这才到SimpleUrlHandlerMapping干活的地方,迭代urlMap调用AbstractUrlHandlerMapping的registerHandler进行注册
(保障url以"/"开头就不多说了)
// SimpleUrlHandlerMapping
/** * Register all handlers specified in the URL map for the corresponding paths. * @param urlMap Map with URL paths as keys and handler beans or bean names as values * @throws BeansException if a handler couldn't be registered * @throws IllegalStateException if there is a conflicting handler registered */ protected void registerHandlers(Map<String, Object> urlMap) throws BeansException { if (urlMap.isEmpty()) { logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping"); } else { for (Map.Entry<String, Object> entry : urlMap.entrySet()) { String url = entry.getKey(); Object handler = entry.getValue(); // Prepend with slash if not already present. if (!url.startsWith("/")) { url = "/" + url; } // Remove whitespace from handler bean name. if (handler instanceof String) { handler = ((String) handler).trim(); } registerHandler(url, handler); } } }
// AbstractUrlHandlerMapping
/** * Register the specified handler for the given URL path. * @param urlPath the URL the bean should be mapped to * @param handler the handler instance or handler bean name String * (a bean name will automatically be resolved into the corresponding handler bean) * @throws BeansException if the handler couldn't be registered * @throws IllegalStateException if there is a conflicting handler registered */ protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { Assert.notNull(urlPath, "URL path must not be null"); Assert.notNull(handler, "Handler object must not be null"); Object resolvedHandler = handler; // Eagerly resolve handler if referencing singleton via name.不是单例同时不是懒加载 if (!this.lazyInitHandlers && handler instanceof String) { String handlerName = (String) handler; if (getApplicationContext().isSingleton(handlerName)) { resolvedHandler = getApplicationContext().getBean(handlerName); } } Object mappedHandler = this.handlerMap.get(urlPath);// 获取之前已经匹配的Handler if (mappedHandler != null) { if (mappedHandler != resolvedHandler) {// 如果新匹配得到的跟之前已解析到的handler不一致,则抛异常 throw new IllegalStateException( "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + getHandlerDescription(mappedHandler) + " mapped."); } } else { if (urlPath.equals("/")) {// 设置rootHandler if (logger.isInfoEnabled()) { logger.info("Root mapping to " + getHandlerDescription(handler)); } setRootHandler(resolvedHandler); } else if (urlPath.equals("/*")) {// 设置默认的defaultHandler if (logger.isInfoEnabled()) { logger.info("Default mapping to " + getHandlerDescription(handler)); } setDefaultHandler(resolvedHandler); } else {// 最后才是普通handler的设置 this.handlerMap.put(urlPath, resolvedHandler); if (logger.isInfoEnabled()) { logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler)); } } } }
相关文章推荐
- Android进程间通讯——多进程共用SharedPreferences
- android碰见的问题(1)
- Android平台中关于音频播放
- New Activity探索(序)
- instancetype、id、NSObject的区别
- boost for android
- 写一个Android输入法02——候选窗、转换
- 写一个Android输入法01——最简步骤
- SoftKeyboard在AndroidStudio下的配置和运行
- Android开发之Intent跳转到系统应用中的拨号界面、联系人界面、短信界面
- Android下创建一个输入法
- iOS模拟器录屏转gif神器
- iOS Programming GitHub
- iOS海哥开发笔记(MapKit的使用)
- iOS 处理方法中的可变參数
- Android studio 打签名包 以及在真机上编译运行
- iOS模拟器的应用沙盒在MAC中的位置
- iOS - 性能优化
- Android MediaRecorder问题:StartFailed解决方案
- 获取控件高度—最简单也最难——如何获取到Android控件的高度