Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化

來源:互聯網
上載者:User

標籤:ORC   style   rip   sde   file   邏輯   protect   這一   不同   

先介紹一下:

  BeanNameUrlHandlerMapping是基於設定檔的方式; 所有處理器需要在XML檔案中,以Bean的形式配置。

  缺點:配置繁瑣; 如果多個URL對應同一個處理器,那麼需要配置多條,同時也會執行個體化多個對象等等。。。

  因為springmvc 是基於spring的,所以他的初始化肯定是在spring容器初始化之後才進行的。

先上類圖:

  

可以看到BeanNameUrlHandlerMapping父類最終實現了ApplicationContextAware介面,所以Spring容器會自動注入ApplicationContext,方法為:

 1     public final void setApplicationContext(ApplicationContext context) throws BeansException { 2         if (context == null && !this.isContextRequired()) { 3             this.applicationContext = null; 4             this.messageSourceAccessor = null; 5         } else if (this.applicationContext == null) { 6             if (!this.requiredContextClass().isInstance(context)) { 7                 throw new ApplicationContextException("Invalid application context: needs to be of type [" + this.requiredContextClass().getName() + "]"); 8             } 9 10             this.applicationContext = context;11             this.messageSourceAccessor = new MessageSourceAccessor(context);12             this.initApplicationContext(context);  //這塊實際上是一個鉤子方法,供子類去覆蓋! 進行初始化工作13         } else if (this.applicationContext != context) {14             throw new ApplicationContextException("Cannot reinitialize with different application context: current one is [" + this.applicationContext + "], passed-in one is [" + context + "]");15         }16 17     }

AbstractHandlerMapping: 這個類就是複寫了這個方法 進行了攔截器的初始化

    protected void initApplicationContext() throws BeansException {        this.extendInterceptors(this.interceptors); //供子類擴充攔截器        this.detectMappedInterceptors(this.mappedInterceptors);//掃描應用下的MappedInterceptor,並添加到mappedInterceptors        this.initInterceptors();//歸集MappedInterceptor,並適配HandlerInterceptor和WebRequestInterceptor    }

AbstractDetectingUrlHandlerMapping :同樣重寫這個方法,實現自己的邏輯

 1     public void initApplicationContext() throws ApplicationContextException { 2         super.initApplicationContext(); 3         this.detectHandlers(); 4     } 5      6     protected void detectHandlers() throws BeansException { 7         if (this.logger.isDebugEnabled()) { 8             this.logger.debug("Looking for URL mappings in application context: " + this.getApplicationContext()); 9         }10      // 掃描應用下所有的Object類11         String[] beanNames = this.detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.getApplicationContext(), Object.class) : this.getApplicationContext().getBeanNamesForType(Object.class);12         String[] arr$ = beanNames;13         int len$ = beanNames.length;14 15         for(int i$ = 0; i$ < len$; ++i$) { //遍曆每一個掃描出來的類16             String beanName = arr$[i$];17             String[] urls = this.determineUrlsForHandler(beanName); //鉤子方法,讓子類去實現,通過handler解析url18             if (!ObjectUtils.isEmpty(urls)) {19                 this.registerHandler(urls, beanName); //返回的URL進行註冊,實際上就是放到AbstractUrlHandlerMapping的一個map中20             } else if (this.logger.isDebugEnabled()) {21                 this.logger.debug("Rejected bean name ‘" + beanName + "‘: no URL paths identified");22             }23         }24 25     }

BeanNameUrlHandlerMapping:實際上就實現了determineUrlsForHandler這個方法:

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package org.springframework.web.servlet.handler;import java.util.ArrayList;import java.util.List;import org.springframework.util.StringUtils;public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {    public BeanNameUrlHandlerMapping() {    }    protected String[] determineUrlsForHandler(String beanName) {        List<String> urls = new ArrayList();        if (beanName.startsWith("/")) { //只有一點需要注意 就是bean id 必須是以‘/‘開頭            urls.add(beanName);        }        String[] aliases = this.getApplicationContext().getAliases(beanName);        String[] arr$ = aliases;        int len$ = aliases.length;        for(int i$ = 0; i$ < len$; ++i$) {            String alias = arr$[i$];            if (alias.startsWith("/")) {                urls.add(alias);            }        }        return StringUtils.toStringArray(urls);    }}

AbstractUrlHandlerMappin:中註冊處理器的方法:

 1     protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { 2         Assert.notNull(urlPath, "URL path must not be null"); 3         Assert.notNull(handler, "Handler object must not be null"); 4         Object resolvedHandler = handler; 5         if (!this.lazyInitHandlers && handler instanceof String) { 6             String handlerName = (String)handler; 7             if (this.getApplicationContext().isSingleton(handlerName)) { 8                 resolvedHandler = this.getApplicationContext().getBean(handlerName); 9             }10         }11 12         Object mappedHandler = this.handlerMap.get(urlPath);13         if (mappedHandler != null) {14             if (mappedHandler != resolvedHandler) { //不允許存在相同url不同handler,否則拋異常15                 throw new IllegalStateException("Cannot map " + this.getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + this.getHandlerDescription(mappedHandler) + " mapped.");16             }17         } else if (urlPath.equals("/")) {18             if (this.logger.isInfoEnabled()) {19                 this.logger.info("Root mapping to " + this.getHandlerDescription(handler));20             }21 22             this.setRootHandler(resolvedHandler);23         } else if (urlPath.equals("/*")) {24             if (this.logger.isInfoEnabled()) {25                 this.logger.info("Default mapping to " + this.getHandlerDescription(handler));26             }27 28             this.setDefaultHandler(resolvedHandler);29         } else { //這才是正常的儲存邏輯30             this.handlerMap.put(urlPath, resolvedHandler);31             if (this.logger.isInfoEnabled()) {32                 this.logger.info("Mapped URL path [" + urlPath + "] onto " + this.getHandlerDescription(handler));33             }34         }35 36     }

到這裡實際上處理器映射器的儲存工作就算完事了。 

實際上handlerMapping這一塊,主要思路就是 寫一個模板類,來處理公用的方法,如初始化攔截器,然後留下鉤子方法,讓子類去實現自己的邏輯就好了。

Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.