先介绍一下:

  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. 网页版Rstudio︱RStudio Server多人在线协作开发

    网页版Rstudio︱RStudio Server多人在线协作开发 想了解一下RStudio Server,太给力的应用,可以说成是代码分布式运行,可以节省时间,放大空间. RStudio是一个非常优 ...

  2. R语言自动化报告格式——knitr

    R语言自动化报告格式--knitr 相关文献: R语言自动化报告格式--knitr 资讯 | R Notebooks 即将发布 ------------------------------------ ...

  3. 安装STS报错(一)

    安装STS报错 1.具体报错如下 2.报错原因 3.解决办法

  4. hi3531的pcie atu资源重映射

    1. 设置ATU 区域号寄存器为需要配置的地址转换区编号. 2. 设置ATU Region Lower Base Address Register 和ATU Region Upper Base Add ...

  5. Struts 有哪些常用标签库

    Struts 有哪些常用标签库 1.html标签库 2.bean标签库 3.logic标签库

  6. freemark标签从后台接过来数据Boolean在前台还是Boolean输出(四)

    FREEMARK标签中输出BOOLEAN值 private boolean showHeader=true; public boolean getShowHeader(){ return this.s ...

  7. 过滤文件代码 python

    import os import cv2 import shutil # store all file in directory global totalFileList totalFileList ...

  8. html点小图看大图最快捷的方法

    方法一: <td> <a href="{$vo.show_img}" target="_blank"><img style=&qu ...

  9. 分类导航菜单的制作(附源码)--HTML

    不多说,直接贴代码哈!有疑问,可追加评论哈! demo.html: <!DOCTYPE html><html> <head> <title>分类导航菜单 ...

  10. Android继承AppCompatActivity实现全屏设置

    转载 2016年05月25日 13:20:25 标签: android / style / android studio / 继承 4839 Android studio创建新项目后Activity默 ...