SpringMVC源码解读 - HandlerMapping - SimpleUrlHandlerMapping初始化

摘要:

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

1     /**
2      * Calls the {@link #registerHandlers} method in addition to the
3      * superclass's initialization.
4      */
5     @Override
6     public void initApplicationContext() throws BeansException {
7         super.initApplicationContext();
8         registerHandlers(this.urlMap);
9     }

 

initApplicationContext主要是进行拦截器的初始化.

  extendInterceptors是留给子类用的扩展接口,暂时没有使用

  detectMappedInterceptors是通过BeanFactoryUtils扫描应用下的全部MappedInterceptor类

  initInterceptors初始化特定的拦截器,检查MappedInterceptor,在需要时适配adaptor HandlerInterceptor

// AbstractHandlerMapping

 1     /**
 2      * Initializes the interceptors.
 3      * @see #extendInterceptors(java.util.List)
 4      * @see #initInterceptors()
 5      */
 6     @Override
 7     protected void initApplicationContext() throws BeansException {
 8         extendInterceptors(this.interceptors);
 9         detectMappedInterceptors(this.mappedInterceptors);
10         initInterceptors();
11     }

 

// AbstractHandlerMapping

 1     /**
 2      * Extension hook that subclasses can override to register additional interceptors,
 3      * given the configured interceptors (see {@link #setInterceptors}).
 4      * <p>Will be invoked before {@link #initInterceptors()} adapts the specified
 5      * interceptors into {@link HandlerInterceptor} instances.
 6      * <p>The default implementation is empty.
 7      * @param interceptors the configured interceptor List (never {@code null}),
 8      * allowing to add further interceptors before as well as after the existing
 9      * interceptors
10      */
11     protected void extendInterceptors(List<Object> interceptors) {
12     }

 

springmvc中经常使用BeanFactoryUtils扫描应用下的类来进行初始化.

// AbstractHandlerMapping

 1     /**
 2      * Detects beans of type {@link MappedInterceptor} and adds them to the list of mapped interceptors.
 3      * This is done in addition to any {@link MappedInterceptor}s that may have been provided via
 4      * {@link #setInterceptors(Object[])}. Subclasses can override this method to change that.
 5      *
 6      * @param mappedInterceptors an empty list to add MappedInterceptor types to
 7      */
 8     protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
 9         mappedInterceptors.addAll(
10                 BeanFactoryUtils.beansOfTypeIncludingAncestors(
11                         getApplicationContext(),MappedInterceptor.class, true, false).values());
12     }

 

// AbstractHandlerMapping

 1     /**
 2      * Initialize the specified interceptors, checking for {@link MappedInterceptor}s and adapting
 3      * HandlerInterceptors where necessary.
 4      * @see #setInterceptors
 5      * @see #adaptInterceptor
 6      */
 7     protected void initInterceptors() {
 8         if (!this.interceptors.isEmpty()) {
 9             for (int i = 0; i < this.interceptors.size(); i++) {
10                 Object interceptor = this.interceptors.get(i);
11                 if (interceptor == null) {
12                     throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
13                 }
14                 if (interceptor instanceof MappedInterceptor) {
15                     mappedInterceptors.add((MappedInterceptor) interceptor);
16                 }
17                 else {
18                     adaptedInterceptors.add(adaptInterceptor(interceptor));
19                 }
20             }
21         }
22     }

 

适配HandlerInterceptor和WebRequestHandlerInterceptorAdapter(什么是WebRequestHandlerInterceptorAdapter,晚点再说吧,具体看到时候拦截器部分的分析)

// AbstractHandlerMapping

 1     /**
 2      * Adapt the given interceptor object to the HandlerInterceptor interface.
 3      * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
 4      * Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
 5      * Can be overridden in subclasses.
 6      * @param interceptor the specified interceptor object
 7      * @return the interceptor wrapped as HandlerInterceptor
 8      * @see org.springframework.web.servlet.HandlerInterceptor
 9      * @see org.springframework.web.context.request.WebRequestInterceptor
10      * @see WebRequestHandlerInterceptorAdapter
11      */
12     protected HandlerInterceptor adaptInterceptor(Object interceptor) {
13         if (interceptor instanceof HandlerInterceptor) {
14             return (HandlerInterceptor) interceptor;
15         }
16         else if (interceptor instanceof WebRequestInterceptor) {
17             return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
18         }
19         else {
20             throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
21         }
22     }

 

这才到SimpleUrlHandlerMapping干活的地方,迭代urlMap调用AbstractUrlHandlerMapping的registerHandler进行注册

(保障url以"/"开头就不多说了)

// SimpleUrlHandlerMapping

 1     /**
 2      * Register all handlers specified in the URL map for the corresponding paths.
 3      * @param urlMap Map with URL paths as keys and handler beans or bean names as values
 4      * @throws BeansException if a handler couldn't be registered
 5      * @throws IllegalStateException if there is a conflicting handler registered
 6      */
 7     protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
 8         if (urlMap.isEmpty()) {
 9             logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
10         }
11         else {
12             for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
13                 String url = entry.getKey();
14                 Object handler = entry.getValue();
15                 // Prepend with slash if not already present.
16                 if (!url.startsWith("/")) {
17                     url = "/" + url;
18                 }
19                 // Remove whitespace from handler bean name.
20                 if (handler instanceof String) {
21                     handler = ((String) handler).trim();
22                 }
23                 registerHandler(url, handler);
24             }
25         }
26     }

 

 

// AbstractUrlHandlerMapping

 1 /**
 2      * Register the specified handler for the given URL path.
 3      * @param urlPath the URL the bean should be mapped to
 4      * @param handler the handler instance or handler bean name String
 5      * (a bean name will automatically be resolved into the corresponding handler bean)
 6      * @throws BeansException if the handler couldn't be registered
 7      * @throws IllegalStateException if there is a conflicting handler registered
 8      */
 9     protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
10         Assert.notNull(urlPath, "URL path must not be null");
11         Assert.notNull(handler, "Handler object must not be null");
12         Object resolvedHandler = handler;
13 
14         // Eagerly resolve handler if referencing singleton via name.不是单例同时不是懒加载
15         if (!this.lazyInitHandlers && handler instanceof String) {
16             String handlerName = (String) handler;
17             if (getApplicationContext().isSingleton(handlerName)) {
18                 resolvedHandler = getApplicationContext().getBean(handlerName);
19             }
20         }
21 
22         Object mappedHandler = this.handlerMap.get(urlPath);// 获取之前已经匹配的Handler
23         if (mappedHandler != null) {
24             if (mappedHandler != resolvedHandler) {// 如果新匹配得到的跟之前已解析到的handler不一致,则抛异常
25                 throw new IllegalStateException(
26                         "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
27                         "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
28             }
29         }
30         else {
31             if (urlPath.equals("/")) {// 设置rootHandler
32                 if (logger.isInfoEnabled()) {
33                     logger.info("Root mapping to " + getHandlerDescription(handler));
34                 }
35                 setRootHandler(resolvedHandler);
36             }
37             else if (urlPath.equals("/*")) {// 设置默认的defaultHandler
38                 if (logger.isInfoEnabled()) {
39                     logger.info("Default mapping to " + getHandlerDescription(handler));
40                 }
41                 setDefaultHandler(resolvedHandler);
42             }
43             else {// 最后才是普通handler的设置
44                 this.handlerMap.put(urlPath, resolvedHandler);
45                 if (logger.isInfoEnabled()) {
46                     logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
47                 }
48             }
49         }
50     }

 

posted @ 2016-02-22 17:45  出门向左  阅读(2044)  评论(0编辑  收藏  举报