前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring MVC介绍(三)之 Annotation解析以及完整的执行流程

Spring MVC介绍(三)之 Annotation解析以及完整的执行流程

作者头像
zoro
发布2019-04-11 15:17:42
9190
发布2019-04-11 15:17:42
举报
文章被收录于专栏:Java开发者Java开发者

Spring MVC介绍(三)之 Annotation解析以及完整的执行流程

工作中对于Spring MVC我们最常用的还是使用注解的方式,那么对于注解Spring MVC的如何处理的?

代码语言:javascript
复制
<context:component-scan base-package="com.demo.spring.mvc.control" />
<mvc:annotation-driven/>
一、annotation-driven

在前面的介绍中,我们知道了HandlerMapping以及HandlerAdapter,那么annotation的是什么?

对于注解:

代码语言:javascript
复制
<mvc:annotation-driven/>

它对应的handlerMapping则是:

代码语言:javascript
复制
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

对应的HandlerAdapter则是:

代码语言:javascript
复制
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

对应的Handler则是:

代码语言:javascript
复制
org.springframework.web.method.HandlerMethod

这些没有配置在配置文件中,注解是怎么实现的?

来看下NamespaceHandler接口:

代码语言:javascript
复制
org.springframework.beans.factory.xml.NamespaceHandler

package org.springframework.beans.factory.xml;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;

public interface NamespaceHandler {

    void init();

    BeanDefinition parse(Element element, ParserContext parserContext);

    BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);

}

实现这个接口,则就可以动态的往ioc容器添加BeanDefinition,则就动态的添加了bean。

那么这个是在哪实现的呢?

来看下spring-webmvc包里面的spring.handlers

代码语言:javascript
复制
org\springframework\spring-webmvc\4.3.8.RELEASE\spring-webmvc-4.3.8.RELEASE.jar!\META-INF\spring.handlers

里面内容:

代码语言:javascript
复制
http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler

点进去看一下 MvcNamespaceHandler 这个类:

代码语言:javascript
复制
package org.springframework.web.servlet.config;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class MvcNamespaceHandler extends NamespaceHandlerSupport {
    public MvcNamespaceHandler() {
    }

    public void init() {
        this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        this.registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
        this.registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
        this.registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
        this.registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
        this.registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
        this.registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
        this.registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
        this.registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
    }
}

此时我们看到了MvcNamespaceHandler extends NamespaceHandlerSupport

代码语言:javascript
复制
public class MvcNamespaceHandler extends NamespaceHandlerSupport{...}

NamespaceHandlerSupport implements NamespaceHandler

代码语言:javascript
复制
public abstract class NamespaceHandlerSupport implements NamespaceHandler {}

NamespaceHandler接口就是我们刚刚看到的那个动态注册BeanDefinition的接口。

并且在MvcNamespaceHandler.init() 方法中,可以看到:

代码语言:javascript
复制
this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());

并且 AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser

代码语言:javascript
复制
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {}

其中 BeanDefinitionParser 接口:

代码语言:javascript
复制
public interface BeanDefinitionParser {

BeanDefinition parse(Element element, ParserContext parserContext);
}

AnnotationDrivenBeanDefinitionParser.parse() 的实现方法中,可以看到 RequestMappingHandlerMapping 被注册到ioc容器中:

代码语言:javascript
复制
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);

同样的还有RequestMappingHandlerAdapter

代码语言:javascript
复制
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);

所以这就是为什么添加了 <mvc:annotation-driven/> 配置,就能实现mvc的整个配置了。

二、MVC完整的执行流程

之前我们介绍了MVC的异常处理和拦截器,那么加上这两部分,MVC的执行流程如下:

代码语言:javascript
复制
DispatcherServlet ==> 找到下面这些组件(1:n)
HandlerMapping ==> 基于url找到对应的handler (其实是找到HandlerExecutionChain)
HandlerAdapter ==> 基于handler找到对应的适配器 调用handler返回ModelAndView
(如果出现了异常)
HandlerExceptionResovler ==> 处理异常 返回errorModelAndView
(如果加入了拦截器)
HandlerInterceptor ==> 处理拦截器
ViewResolver   ==> 视图仓库 ==> 基于viewName找到View => 解析生成Html

其中 DispatcherServlet 中调用 initStrategies 来初始化上述组件。

代码语言:javascript
复制
org.springframework.web.servlet.DispatcherServlet#initStrategies

protected void initStrategies(ApplicationContext context) {
    this.initMultipartResolver(context);
    this.initLocaleResolver(context);
    this.initThemeResolver(context);
    this.initHandlerMappings(context);
    this.initHandlerAdapters(context);
    this.initHandlerExceptionResolvers(context);
    this.initRequestToViewNameTranslator(context);
    this.initViewResolvers(context);
    this.initFlashMapManager(context);
}

有兴趣可以看下这些init方法实现。


本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.02.25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring MVC介绍(三)之 Annotation解析以及完整的执行流程
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档