2019独角兽企业重金招聘Python工程师标准>>>

一、AnnotationDrivenBeanDefinitionParser

通常如果我们希望通过注解的方式来进行Spring MVC开发,我们都会在***-servlet.xml中加入<mvc:annotation-driven/>标签来告诉Spring我们的目的。但是我们为什么这么做呢?这个标签是什么意思呢?它做了什么呢?

同样为了弄清楚这些问题, 像<context:component-scan/>标签一样,我们先找到它的解析类。第一篇文章中说过了,所有的自定义命名空间(像mvc,context等)下的标签解析都是由BeanDefinitionParser接口的子类来完成的。参看第一篇文章中的图片

我们看到有多个AnnotationDrivenBeanDefinitionParser,他们是用来处理不同命名空间下的<annotation-driven/>标签的,我们今天研究的是<mvc:annotation-driven/>标签,所以我们找到对应的实现类是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser。
    通过阅读类注释文档,我们发现这个类主要是用来向工厂中注册:

  • RequestMappingHandlerMapping

  • BeanNameUrlHandlerMapping

  • RequestMappingHandlerAdapter

  • HttpRequestHandlerAdapter

  • SimpleControllerHandlerAdapter

  • ExceptionHandlerExceptionResolver

  • ResponseStatusExceptionResolver

  • DefaultHandlerExceptionResolver

上面几个Bean实例。这几个类都是用来做什么的呢?

前两个是HandlerMapping接口的实现类,用来处理请求映射的。其中第一个是处理@RequestMapping注解的。第二个会将controller类的名字映射为请求url。

中间三个是用来处理请求的。具体点说就是确定调用哪个controller的哪个方法来处理当前请求。第一个处理@Controller注解的处理器,支持自定义方法参数和返回值(很酷)。第二个是处理继承HttpRequestHandler的处理器。第三个处理继承自Controller接口的处理器。

后面三个是用来处理异常的解析器。

二、实现

光说无凭据,我们直接看代码:

public BeanDefinition parse(Element element, ParserContext parserContext) {Object source = parserContext.extractSource(element);CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);parserContext.pushContainingComponent(compDefinition);RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);//第一个在这 RequestMappingHandlerMappingRootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);handlerMappingDef.setSource(source);handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);handlerMappingDef.getPropertyValues().add("order", 0);handlerMappingDef.getPropertyValues().add("removeSemicolonContent", false);handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);//第二个在这 RequestMappingHandlerAdapterRootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);handlerAdapterDef.setSource(source);handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);}if (argumentResolvers != null) {handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);}if (returnValueHandlers != null) {handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);}if (asyncTimeout != null) {handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);}if (asyncExecutor != null) {handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);}handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);//异常处理解析器RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);exceptionHandlerExceptionResolver.setSource(source);exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);String methodExceptionResolverName =parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);//异常处理解析器RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);responseStatusExceptionResolver.setSource(source);responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);responseStatusExceptionResolver.getPropertyValues().add("order", 1);String responseStatusExceptionResolverName =parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);//异常处理解析器RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);defaultExceptionResolver.setSource(source);defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);defaultExceptionResolver.getPropertyValues().add("order", 2);String defaultExceptionResolverName =parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));//这里注册了BeanNameUrlHandlerMapping,SimpleControllerHandlerAdapter等// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"MvcNamespaceUtils.registerDefaultComponents(parserContext, source);parserContext.popAndRegisterContainingComponent();return null;}
//在这啊。
public static void registerDefaultComponents(ParserContext parserContext, Object source) {registerBeanNameUrlHandlerMapping(parserContext, source);registerHttpRequestHandlerAdapter(parserContext, source);registerSimpleControllerHandlerAdapter(parserContext, source);}

略长,但很容易看明白的代码。看注释我们发现,它的确注册了上面说的那几个类。

三、总结

我们知道了它们自动为我们注册了这么多的Bean,那这些Bean是做什么的呢?

我们主要说明里面的两个,RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

第一个是HandlerMapping的实现类,它会处理@RequestMapping 注解,并将其注册到请求映射表中。(下片文章我们会详细介绍的)

第二个是HandlerAdapter的实现类,它是处理请求的适配器,说白了,就是确定调用哪个类的哪个方法,并且构造方法参数,返回值。(后面文章也会陆续详细介绍的)

那么它跟<context:component-scan/>有什么区别呢?其实想上篇文章中介绍的,<context:component-scan/>标签是告诉Spring 来扫描指定包下的类,并注册被@Component,@Controller,@Service,@Repository等注解标记的组件。

而<mvc:annotation-driven/>是告知Spring,我们启用注解驱动。然后Spring会自动为我们注册上面说到的几个Bean到工厂中,来处理我们的请求。

转载于:https://my.oschina.net/thinwonton/blog/1301806

Spring MVC 解读——mvc:annotation-driven/相关推荐

  1. Spring MVC 解读——@Autowired

    2019独角兽企业重金招聘Python工程师标准>>> Spring MVC 解读--@Autowired 一.@Autowired 作为一个Spring开发者对@Autowired ...

  2. Spring MVC 解读——@Autowired、@Controller、@Service从原理层面来分析

    Spring MVC 解读--@Autowired 一.@Autowired 作为一个Spring开发者对@Autowired注解必定是非常了解了, 顾名思义自动装配,应该是Spring会自动将我们标 ...

  3. Spring MVC 解读——context:component-scan/

    2019独角兽企业重金招聘Python工程师标准>>> Spring MVC 解读---<context:component-scan/> 注解是骑士魂牵梦绕的美丽公主, ...

  4. 在controller中调用指定参数给指定表单_第005课:Spring Boot 中MVC支持

    Spring Boot 的 MVC 支持主要介绍实际项目中最常用的几个注解,包括 @RestController. @RequestMapping.@PathVariable.@RequestPara ...

  5. Spring的Web MVC –重定向到内存泄漏

    他们说一块岩石会引起雪崩. 最近,我的一位同事Marcin Radoszewski给了我一块岩石. 您可能永远都不会猜测它是什么,但是有机会在许多Web应用程序中使用它. 请允许我向您介绍这块石头. ...

  6. 【Spring框架】mvc:default-servlet-handler/的作用

    优雅REST风格的资源URL不希望带 .html 或 .do 等后缀.由于早期的Spring MVC不能很好地处理静态资源,所以在web.xml中配置DispatcherServlet的请求映射,往往 ...

  7. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)(转)

    阅读目录 一.MVC原理解析 1.MVC原理 二.HttpHandler 1.HttpHandler.IHttpHandler.MvcHandler的说明 2.IHttpHandler解析 3.Mvc ...

  8. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...

  9. Spring事务管理-》Spring事务管理(annotation)

    5.6 使用@Transactional 除了使用XML类型的事务管理,同时Spring也提供了Annotation类型的事务管理.如下所示: 一:Spring事务管理 =============== ...

最新文章

  1. C#之windows桌面软件第十二课:电脑ADC值显示(上位机),记忆上次串口号,并用TrackBar控件显示ADC值
  2. 问题 | fatal: open /dev/null or dup failed: No Such file or directory
  3. gridcontrol值为0时设置为空_CSS设置宽高的小技巧
  4. java order()_java.util.Collections.reverseOrder()
  5. 编写c语言程序的可视化编程环境有哪些,C语言可视化编程环境设计及实现.pdf
  6. 计算机组成与设计第五版英文_教学设计gt;小学信息技术计算机的组成教师资格证面试模板...
  7. 提升网页加载速度—预加载VS预读取
  8. mysql修改表、字段、库的字符集
  9. 机器学习算法:马尔可夫链
  10. webpack5学习与实战-(八)-配置打包后的文件名
  11. 华为交换机基本配置,秒看秒懂~~~
  12. 02、差分特性阻抗仿真
  13. Xshell 6安装和使用教程
  14. 关于Jenkins下载代码失败,“Error cloning remote repo ‘origin‘“
  15. 验证座机号码是否输入格式正确
  16. 某些型号的Comba和D-Link路由器存在管理员密码泄露漏洞
  17. 国外博士论文下载网址
  18. 你对Redis的使用靠谱吗?
  19. wx.getImageInfo(Object object)获取图片信息
  20. 万年历(hao123)代码

热门文章

  1. android ios 7 双环,安卓机泪奔 库克嘲笑Android 7安装率不及iOS 10零头
  2. python中isinstance(3、object)_Python中为什么推荐使用isinstance来进行类型判断?而不是type...
  3. putchar(c1)在C语言中表示,C语言中的getchar和putchar详解
  4. react怎么存上一页_如何实现 React 中的状态自动保存?
  5. python动态网页开发教程_python django创建一个属于自己的动态网站
  6. java round number,Java Number Math 类
  7. Apriltag : 用于视觉系统标定图标tag36H11
  8. 特使招募-航天三院-智能车竞赛
  9. 一种互补间歇振荡器工作电压
  10. 人工智能还给我们留多少空间?