网站首页 > 技术教程 正文
<context:component-scan />和<mvc:annotation-driven>完全实现不同的目的。
<context:component-scan /> 如名字表示的意思一样,用于组件扫描。默认扫描 @Component 注解的组件(或者子注解,如 @Controller、@Service等等)。它仅仅注册这些类的实例到 application context中,作为beans。
<mvc:annotation-driven />用来启动Spring MVC,并注册 RequestMappingHandlerMapping和RequestMappingHandlerAdapter,和其他一些beans。第一个用来连接请求到特定方法(在@Controller 注解类中的 @RequestMapping 注解方法)。最后一个知道如何执行 @RequestMapping 注解的方法。
如果在aplication context 中没有beans,<mvc:annotation-driven /> 不负责扫描或检测 @Controllers,这样就无法处理 request mappings。现在,有几种方法注册这些beans 到application context 中,其中之一就是前面提及的 <context:component-scan />。
一般而言,如果一个 @Controller 没有 <mvc:annotation-driven />配置,就没有任何用处了(除了占用内存而已)。它就无法绑定到进入的请求,仅仅在application context 中挂着。它就像其他的beans一样,没有什么特殊的地方。
(最近,过期版本的Spring 注册了DefaultAnnotationHandlerMapping bean,它负责处理 @Controller,但是已经过期了。)
从IoC容器中查找相应的配置,如果查找不到,就使用DispatcherServlet.properties 默认配置并把配置的类型加入到 IoC 中作为Bean。
如下是 DispatcherServlet.properties 文件内容:
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.
DispatcherServlet的策略接口的默认实现类。
当在DispatcherServlet 上下文中没有找到匹配的beans,则当做备份beans来使用。
annotation-driven用于打开注解驱动。
一般根据前缀来注册相关的注解类:
<tx:annotation-driven/>:支持事务注解的(@Transactional)。
<mvc:annotation-driven/>:支持MVC注解。
component-scan 和 annotation-driven 源码解析
- component-scan:扫描指定包下被@Component,@Service,@Controller,@Repository,@Configuration注解所标注的class。实际上,都是通过@Component来完成的。
- annotation-driven:注册Spring MVC的web组件,并完成HandlerMethod的解析。
context:component-scan标签由ContextNamespaceHandler处理器处理。
mvc:annotation-driven标签由MvcNamespaceHandler处理器处理。
ContextNamespaceHandler 处理器源码:
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
由此可见,component-scan是由具体的ComponentScanBeanDefinitionParser解析器解析,它实现了BeanDefinitionParser接口,完成扫描指定包路径下的class文件,并注册所有满足条件的BeanDefinition。
MvcNamespaceHandler 处理器源码:
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
}
AnnotationDrivenBeanDefinitionParser.parse()方法很长:
...
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
parserContext.registerComponent(new BeanComponentDefinition(exceptionResolver, methodExceptionResolverName));
parserContext.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));
parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
...
mvc:annotation-driven解析器,向Spring IOC容器注册了很多SpringMVC的web组件,我们重点关注下面几个组件,其余读者可自行了解:
1、RequestMappingHandlerMapping:负责解析HandlerMethod,并根据request请求返回HandlerExecutionChain,HandlerExecutionChain是HandlerMethod和方法拦截器的合体。
2、RequestMappingHandlerAdapter:负责处理request请求,并返回ModelAndView对象。
3、DefaultFormattingConversionService:类型转换服务类,如String to Date,Date to String。
4、HttpMessageConverter:消息转换器,如根据HTTP的MIME类型,JavaBean to Json,JavaBean to XML。
5、ConfigurableWebBindingInitializer:WebDataBinder的初始化器。
...
其余可自行查看。
context:component-scan:主要完成bean的解析工作。
mvc:annotation-driven:主要完成从controllor bean中解析出RequestMappingInfo,封装为HandlerMethod对象。
Spring MVC 解读——<mvc:annotation-driven/>
如下是resources/applicationContext.xml 配置文件中,<context:component-scan /> 的使用,配置扫描com.rickie package以及sub-package。
猜你喜欢
- 2024-10-19 Java 项目编译提示 javax.xml.bind.annotation does not exist 错误
- 2024-10-19 Android annotation包下常用的注解
- 2024-10-19 SpringMVC疑难一:mvc:annotation-dr
- 2024-10-19 Spring 中 AnnotationConfigUtils
- 2024-10-19 spring mvc 配置失效了?(springmvc的配置)
- 2024-10-19 为什么都爱着江南?黛瓦白墙,烟雨朦胧,是文人魂牵梦绕的故乡
- 2024-10-19 Spring框架系列之构造方法底层剖析01
- 2024-10-19 基于.NET6包含DDD,ES,CQRS等概念的开源
- 2024-10-19 spring 中 AnnotationUtils 的常用方法
- 2024-10-19 SpringBoot实战4-Spring基础-IoC容器
你 发表评论:
欢迎- 最近发表
-
- Win11学院:如何在Windows 11上使用WSL安装Ubuntu
- linux移植(Linux移植freemodbus)
- 独家解读:Win10预览版9879为何无法识别硬盘
- 基于Linux系统的本地Yum源搭建与配置(ISO方式、RPM方式)
- Docker镜像瘦身(docker 减小镜像大小)
- 在linux上安装ollama(linux安装locale)
- 渗透测试系统Kali推出Docker镜像(kali linux渗透测试技术详解pdf)
- Linux环境中部署Harbor私有镜像仓库
- linux之间传文件命令之Rsync傻瓜式教程
- 解决ollama在linux中安装或升级时,通过国内镜像缩短安装时长
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)