先介绍一下:

  BeanNameUrlHandlerMapping是基于配置文件的方式; 所有处理器需要在XML文件中,以Bean的形式配置。

  缺点:配置繁琐; 如果多个URL对应同一个处理器,那么需要配置多条,同时也会实例化多个对象等等。。。

  因为springmvc 是基于spring的,所以他的初始化肯定是在spring容器初始化之后才进行的。

先上类图:

  

可以看到BeanNameUrlHandlerMapping父类最终实现了ApplicationContextAware接口,所以Spring容器会自动注入ApplicationContext,方法为:

     public final void setApplicationContext(ApplicationContext context) throws BeansException {
if (context == null && !this.isContextRequired()) {
this.applicationContext = null;
this.messageSourceAccessor = null;
} else if (this.applicationContext == null) {
if (!this.requiredContextClass().isInstance(context)) {
throw new ApplicationContextException("Invalid application context: needs to be of type [" + this.requiredContextClass().getName() + "]");
} this.applicationContext = context;
this.messageSourceAccessor = new MessageSourceAccessor(context);
this.initApplicationContext(context); //这块实际上是一个钩子方法,供子类去覆盖! 进行初始化工作
} else if (this.applicationContext != context) {
throw new ApplicationContextException("Cannot reinitialize with different application context: current one is [" + this.applicationContext + "], passed-in one is [" + context + "]");
} }

AbstractHandlerMapping: 这个类就是复写了这个方法 进行了拦截器的初始化

    protected void initApplicationContext() throws BeansException {
this.extendInterceptors(this.interceptors); //供子类扩展拦截器
this.detectMappedInterceptors(this.mappedInterceptors);//扫描应用下的MappedInterceptor,并添加到mappedInterceptors
this.initInterceptors();//归集MappedInterceptor,并适配HandlerInterceptor和WebRequestInterceptor
}

AbstractDetectingUrlHandlerMapping :同样重写这个方法,实现自己的逻辑

     public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
this.detectHandlers();
} protected void detectHandlers() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Looking for URL mappings in application context: " + this.getApplicationContext());
}
     // 扫描应用下所有的Object类
String[] beanNames = this.detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.getApplicationContext(), Object.class) : this.getApplicationContext().getBeanNamesForType(Object.class);
String[] arr$ = beanNames;
int len$ = beanNames.length; for(int i$ = ; i$ < len$; ++i$) { //遍历每一个扫描出来的类
String beanName = arr$[i$];
String[] urls = this.determineUrlsForHandler(beanName); //钩子方法,让子类去实现,通过handler解析url
if (!ObjectUtils.isEmpty(urls)) {
this.registerHandler(urls, beanName); //返回的URL进行注册,实际上就是放到AbstractUrlHandlerMapping的一个map中
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
}
} }

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$ = ; i$ < len$; ++i$) {
String alias = arr$[i$];
if (alias.startsWith("/")) {
urls.add(alias);
}
} return StringUtils.toStringArray(urls);
}
}

AbstractUrlHandlerMappin:中注册处理器的方法:

     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;
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String)handler;
if (this.getApplicationContext().isSingleton(handlerName)) {
resolvedHandler = this.getApplicationContext().getBean(handlerName);
}
} Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) { //不允许存在相同url不同handler,否则抛异常
throw new IllegalStateException("Cannot map " + this.getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + this.getHandlerDescription(mappedHandler) + " mapped.");
}
} else if (urlPath.equals("/")) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Root mapping to " + this.getHandlerDescription(handler));
} this.setRootHandler(resolvedHandler);
} else if (urlPath.equals("/*")) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Default mapping to " + this.getHandlerDescription(handler));
} this.setDefaultHandler(resolvedHandler);
} else { //这才是正常的存储逻辑
this.handlerMap.put(urlPath, resolvedHandler);
if (this.logger.isInfoEnabled()) {
this.logger.info("Mapped URL path [" + urlPath + "] onto " + this.getHandlerDescription(handler));
}
} }

到这里实际上处理器映射器的保存工作就算完事了。

实际上handlerMapping这一块,主要思路就是 写一个模板类,来处理公共的方法,如初始化拦截器,然后留下钩子方法,让子类去实现自己的逻辑就好了。

Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化的更多相关文章

  1. Spring MVC的handlermapping之SimpleUrlHandlerMapping初始化

    前面信息同BeanNameUrlHandlerMapping,这里不再过多分析,详情请看 :Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化 ...

  2. Spring MVC的handlermapping之RequestMappingHandlerMapping初始化

    RequestMappingHandlerMapping:这个handlerMapping是基于注解的同样,先上类图: 通过类图可以看到,同样是继承父类 AbstractHandlerMapping来 ...

  3. Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)

    本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说. 大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入 ...

  4. Spring MVC 梳理 - handlerMapping和handlerAdapter分析

    参考图片 综上所述我们来猜测一下spring mvc 中根据URL找到处理器Controller中相应方法的流程 ①:获取Request的URL ②:从UrlLookup这个map中找到相应的requ ...

  5. spring mvc(4) HandlerMapping

    在前面一节里提到,DispatcherServlet在接收到请求后,通过HandlerMapping找到处理请求对应的Controller(其实处理请求器并不一定是Controller,还可以是Htt ...

  6. spring mvc 自定义Handlermapping

    上次大概写了个可以解决velocity 多视图的东西. 但是实际运用过程中又到处找了些资料看了下.这里 小计下: DispatcherServlet解析过程: ..1..HandlerMapping. ...

  7. Spring MVC:HandlerMapping

    HandlerMapping 的类图 Spring中存在两种类型的handlers.第一种是 handler mappings(处理程序映射).它们的角色定位与前面所描述的功能完全相同.它们尝试将当前 ...

  8. Spring MVC 上下文(ApplicationContext)初始化入口

    Spring 常用上下文容器有哪些 ApplicationContext ClassPathXmlApplicationContext ApplicationContext context = new ...

  9. Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)

    这个思路同样是通过在AbstractHandlerMethodMapping里面来实现getHandlerInternal()实现自己的方法来处理寻找正确的处理器,不懂得请看上一篇. protecte ...

随机推荐

  1. hql查询实例

    1.设计思路 (1)在页面中设计一个下拉框,数据取自数据库: (2)查询是用hql查询. 2.设计实例 (1)Java模型层 public class Tree { private String id ...

  2. Caused by: java.lang.NoClassDefFoundError: org/springframework/web/context/WebApplicationContext

    1.错误描述 严重: A child container failed during start java.util.concurrent.ExecutionException: org.apache ...

  3. zTree实现删除树节点

    zTree实现删除树节点 1.实现源码 <!DOCTYPE html> <html> <head> <title>zTree实现基本树</titl ...

  4. Error:dijit.tree.TreeStoreModel:root query returned 0 items

    1.错误描述 error loading root:                                            Tree.js(第341行) Error:dijit.tre ...

  5. day8(字符串操作)

    一.字符串操作 1.index  #返回字符串的索引值 s = "Hello word" print(s.index('o')) 2.isalnum #检测字符串是否由字母和数字组 ...

  6. Django学习-24-Ajax

    jQuery.Ajax是原生Ajax的封装,它能自动识别浏览器的Ajax对象HttpResponse(status='404',reason='Page Not Found') 原生Ajax使用Xml ...

  7. sass学习笔记--摘录

    //$a: Helvetica, sans-serif //$b: #333 // //body //font: 100% $a //color: $b //$a: red //body //colo ...

  8. 学IT应该看些书?

    第一阶段:<数据结构><数据库><算法><信息系统管理><互联网>第二阶段:<莫生气><佛经><老子>& ...

  9. 【BZOJ4653】【NOI2016】区间(线段树)

    [BZOJ4653][NOI2016]区间(线段树) 题面 BZOJ 题解 \(NOI\)良心送分题?? 既然是最大长度减去最小长度 莫名想到那道反复减边求最小生成树 从而求出最小的比值 所以这题的套 ...

  10. [UOJ207]共价大爷游长沙

    UOJ sol 这题真是太神啦! 对于S集合中的每个点对,给他们随机附上一个相同权值. 两个点在边(x,y)的两侧当且仅当一个点在x的子树中,另一个点不在x的子树中(假设x是y的儿子) 维护一下子树点 ...