mvc:annotation-driven:诠释驱动版权声明

原创
小哥 3年前 (2022-11-11) 阅读数 3 #大杂烩

这是一种可以手动配置的速记形式,以取代这种速记形式。它允许初学者快速应用默认配置方案。 将自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers需要分发请求,即解决@Controller注释使用的前提配置。

它还提供:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持、阅读和写作XML的支持(JAXB,读写JSON的支持(Jackson). 我们处理响应ajax请求时,一对json支持(配置后,连接后jackson的core和mapper打包后,可以自动转换配置文件,而无需写入。json)。

此外,当action写JUnit单元测试时,从。spring IOC容器中取DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,要完成测试,请花时间准确了解这两个在这句话中注册bean。

需要注意的是,在spring mvc 3.1以上,DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter相应的变化是:
DefaultAnnotationHandlerMapping -> RequestMappingHandlerMapping
AnnotationMethodHandlerAdapter -> RequestMappingHandlerAdapter
AnnotationMethodHandlerExceptionResolver -> ExceptionHandlerExceptionResolver

以上所有都在使用中。annotation-driven自动注册后。通信提供了AbstractHandlerMethodMapping , AbstractHandlerMethodAdapter和 AbstractHandlerMethodExceptionResolver为了让用户更容易实现自定义实现类。

通常,如果我们想通过注释的方式来完成。Spring MVC发展,我们都将***-servlet.xml中加入要告知的标签Spring我们的目的,那么这个标签到底做了什么,让我们先看看它的解析类,我们知道所有的自定义名称空间(如)。mvc,context标签解析下的所有BeanDefinitionParser要完成界面的子类,请先看图片:

我们看到多个AnnotationDrivenBeanDefinitionParser,它们用于处理不同的命名空间。标签,我们今天研究的是标签,所以我们发现对应的实现类是:org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser。

一、AnnotationDrivenBeanDefinitionParser

通过阅读类注释文档,我们发现这个类主要用于向工厂注册:

  1. RequestMappingHandlerMapping

  2. BeanNameUrlHandlerMapping

  3. RequestMappingHandlerAdapter

  4. HttpRequestHandlerAdapter

  5. SimpleControllerHandlerAdapter

  6. ExceptionHandlerExceptionResolver

  7. ResponseStatusExceptionResolver

  8. DefaultHandlerExceptionResolver

上面几个Bean例子这些类使用什么?
前两个是HandlerMapping接口的实现类,用于处理请求映射。首先是处理@RequestMapping已注释。第二个遗嘱controller类名映射到请求。url。中间三个用于处理请求。具体点是确定哪个呼叫controller处理当前请求的方法。第一次治疗@Controller注释处理器支持自定义方法参数和返回值。第二个是处理继承问题HttpRequestHandler加工机第三个进程继承自Controller接口的处理器。最后三个是用于处理异常的解析器。

二、实现

  1. public BeanDefinition parse(Element element, ParserContext parserContext) {

  2. Object source = parserContext.extractSource(element);

  3. CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);

  4. parserContext.pushContainingComponent(compDefinition);

  5. RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);

  6. //这里的第一个 RequestMappingHandlerMapping

  7. RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);

  8. handlerMappingDef.setSource(source);

  9. handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

  10. handlerMappingDef.getPropertyValues().add("order", 0);

  11. handlerMappingDef.getPropertyValues().add("removeSemicolonContent", false);

  12. handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);

  13. String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);

  14. //第二个在这里 RequestMappingHandlerAdapter

  15. RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);

  16. handlerAdapterDef.setSource(source);

  17. handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

  18. handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);

  19. handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);

  20. handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);

  21. if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {

  22. Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));

  23. handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);

  24. }

  25. if (argumentResolvers != null) {

  26. handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);

  27. }

  28. if (returnValueHandlers != null) {

  29. handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);

  30. }

  31. if (asyncTimeout != null) {

  32. handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);

  33. }

  34. if (asyncExecutor != null) {

  35. handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);

  36. }

  37. handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);

  38. handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);

  39. String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);

  40. //异常处理分析器

  41. RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);

  42. exceptionHandlerExceptionResolver.setSource(source);

  43. exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

  44. exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);

  45. exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);

  46. exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);

  47. String methodExceptionResolverName =

  48. parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);

  49. //异常处理分析器

  50. RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);

  51. responseStatusExceptionResolver.setSource(source);

  52. responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

  53. responseStatusExceptionResolver.getPropertyValues().add("order", 1);

  54. String responseStatusExceptionResolverName =

  55. parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);

  56. //异常处理分析器

  57. RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);

  58. defaultExceptionResolver.setSource(source);

  59. defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

  60. defaultExceptionResolver.getPropertyValues().add("order", 2);

  61. String defaultExceptionResolverName =

  62. parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);

  63. parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));

  64. parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));

  65. parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));

  66. parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));

  67. parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));

  68. parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));

  69. //在此处注册BeanNameUrlHandlerMapping,SimpleControllerHandlerAdapter等

  70. // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"

  71. MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

  72. parserContext.popAndRegisterContainingComponent();

  73. return null;

  74. }

  75. //在这啊。

  76. public static void registerDefaultComponents(ParserContext parserContext, Object source) {

  77. registerBeanNameUrlHandlerMapping(parserContext, source);

  78. registerHttpRequestHandlerAdapter(parserContext, source);

  79. registerSimpleControllerHandlerAdapter(parserContext, source);

  80. }

我们知道他们已经自动为我们注册了这么多。Bean,那这些Bean它做什么?
最重要的是RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
第一个是HandlerMapping实现类的,它处理@RequestMapping 注释并将其注册到请求映射表中。
第二个是HandlerAdapter实现类是处理请求的适配器,说白了就是确定调用哪个类的哪个方法,构造方法参数并返回值。

这两个Bean前面的文章都有介绍,所以你可以回去看看。

三、小结

综上所述,让我们再次总结一下:

1、Spring如何解析标签的?

首先,必须从“org.springframework.beans.factory.xml.NamespaceHandlerSupport类,在其init方法,注册您自己的解析器,注册。mvc解析器的类是MvcNamespaceHandler。通常每个元素都有一个解析器,例如:。annotation-driven,有一个解析器:前面提到过AnnotationDrivenBeanDefinitionParser。
分析器必须实现org.springframework.beans.factory.xml.BeanDefinitionParser接口,此接口只有一个parse方法,它有两个参数,第一个。org.w3c.dom.Element是我们xml在文件中声明节点,获取此节点信息,即可开始特定业务。

2、Spring你怎么知道该怎么处理mvc开头的标签称为。MvcNamespaceHandler在中注册的解析器如何?

这需要一个"mvc”<–>MvcNamespaceHandler这样的映射关系,那么这个映射关系在哪里?刚刚进来META-INF目录下的spring.handlers:源文件的内容:

  1. http://www.springframework.org/schema/mvc=

  2. org.springframework.web.servlet.config.MvcNamespaceHandler

只要是http\://www.springframework.org/schema/mvc使用命名空间的标签。org.springframework.web.servlet.config.MvcNamespaceHandler中的分析器。
头文件中的内容http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd,实际上不是要在线下载此文件,在spring.schemas文件,定义其指向的内容。org/springframework/web/servlet/config/spring-mvc-3.1.xsd本文件(在jar包里)。
所以,在Spring在中,要使用自己的命名空间:
1,首先需要xsd用于描述自定义元素命名规则的文件,以及Spring配置文件的它在标题中引用。
2,然后需要实现BeanDefinitionParser接口,在接口中。parse方法,分析中的未来Spring出现在配置文件中的元素。(如果xsd声明可以有多个元素,需要实现多个BeanDefinitionParser接口)
3,最后需要继承NamespaceHandlerSupport类,在其init方法,调用registerBeanDefinitionParser方法,将被解析。xml元素已绑定到分析器。
4、在META-INF目录,创建。spring.schemas、spring.handlers文件,按顺序建立最高级的映射关系Spring处理。

四、与的区别

标签是要告诉Spring 扫描指定包下的类并在指定包下注册该类。@Component,@Controller,@Service,@Repository以及其他注释标记的组件。
是告知Spring,我们启用注释驱动。然后Spring将自动为我们注册上述几个Bean到工厂处理我们的请求。

五、与的区别

当我们需要使用注释模式时,直接在中。Spring这些在配置文件中定义。Bean它很笨拙,例如:
使用@Autowired注释,必须提前Spring在集装箱中申报AutowiredAnnotationBeanPostProcessor的Bean:

使用 @Required注释,您必须声明RequiredAnnotationBeanPostProcessor的Bean:

简单地说,使用什么注释,您需要声明相应的BeanPostProcessor这样的说法太不恰当了,而且Spring为我们提供了一种极其方便的注册方式BeanPostProcessor方式,即使用隐式地向 Spring容器注册AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor以及PersistenceAnnotationBeanPostProcessor这4个BeanPostProcessor。

此外,当我们使用注释时,我们通常会配置扫描包路径选项,即e。该配置项实际上包括自动注入上述processor函数,因此在使用之后,你可以保存它,但必须完全配置!以防万一,最好同时申报。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除