Spring MVC 解读---<context:component-scan/>
2015-10-03 22:32
267 查看
Spring MVC 解读---<context:component-scan/>
注解是骑士魂牵梦绕的美丽公主,也是骑士的无法摆脱的噩梦...
一、<context:component-scan/>
想必@Component,@Repository,@Service,@Controller几个常用的Type-Level的Spring MVC注解,大家都很清楚他们的意思跟用途。标记为@Component的类,在使用注解配置的情况下,系统启动时会被自动扫描,并添加到bean工厂中去(省去了配置文件中写bean定义了),另外三个分别表示MVC三层模式中不同层中的组件,他们都是被@Component标记的,所以也会被自动扫描。?
?
二、BeanDefinitionParser
经过仔细的源码阅读,我找到了这个接口BeanDefinitionParser,文档描述说,它是一个用来处理自定义,顶级(<beans/>的直接儿子标签)标签的接口抽象。可以实现它来将自定义的标签转化为 BeanDefinition类。下面是它的接口定义?
或许你开始恼火说这么多跟上面有什么关系,好吧,下面便是我真正要说的,我们来看下它有哪些实现类:
看到了吧,ComponentScanBeanDefinitionParser,正是我们想要的,他就是用来将<context:component-scan/>标签转化为bean 的解析类。那他做了什么呢?
?
我想你会急切的知道ClassPathBeanDefinitionScanner 做了什么?
?
我们再看看
?
三、includeFilters,excludeFilters
可以看到经历了两次筛选,才找到最终的候选Bean,我们来看第一个过滤做了什么??
默认情况下includeFilters是一个含有两个值得List,分别是@Component注解和@ManageBean注解,而excludeFilter是个空List,好吧,现在豁然开朗了吧,原来就是它来筛选我们的@Component标记的类。当然我们可以自定义这两个filters,只需在<context:component-scan/>标签下加两个子标签即可, 像这样:
?
四、BeanDefinitionRegistry
上面代码中我们看到还有一个isCandidateComponent方法,它主要是判断当前类是否是具体的,而非抽象类和接口,以及是否是可以独立创建的没有依赖的?鉴于与我们目前讨论的主题不相关,所以略去,感兴趣的话,可以自己查看下源码。好了,我们既然知道了Spring是怎样通过<context:component-scan/>来扫描,过滤我们的组件了,但是他是怎样将我们定义的组件收集起来供后面的请求处理呢?
我们来看下上面doScan方法中有
?
?
我们可以看到接口中定义了诸多beandefinition的注册,删除,获取等方法,并且Spring为我们提供了三个内部实现,那么运行时,使用了那个实现呢?DefaultListableBeanFactory,是的就是它。它就是SpringMVC 中管理Bean的工厂了,我们来看下,它的registerBeanDefinition是怎样实现的?
?
当然是从ContextLoaderListener开始了入手分析了。
五、ContextLoader
我们查看源码(篇幅问题,不贴代码了,很简答)发现ContextLoaderListener将web application context的初始化动作委托给了ContextLoader了,那ContextLoader做了什么呢??
?
?
?
?
?
既然找到他了,那我们看看他的refresh()方法做了什么呢?
?
五、Bean Factory
这么多代码中,只有第二行与我们当前讨论的主题有关,这一行会尝试获取一个新鲜的BeanFactory,这个BeanFactory与我们之前说的那个BeanDefinitionRegistry有什么关系呢?继续看代码:?
?
Definition到bean工厂中,是不是与我们上边讲到的对上了?
loadBeanDefinition中,Spring会读取xml配置文件,然后会读取里面的bean定义,这一切都是委托给了文章开头的BeanDefinitionParser来完成的,可以看到除了<context:component-scan/>的Parser,还有<mvc:annotation-driven/>的parser,还有<interceptors/>的parser等。是不是比较清晰了?
当然,我们的问题及好奇心远不止这些,这篇文章只是讲解了其中的一小个:系统的初始化做了什么,在什么时候加载我们定义的beans,我们定义的bean被放到了哪里? 等等,现在问题又来了,我们怎样使用我们的bean呢?或者说如果被标记为@Autowire的属性,是怎样被自动装配的呢?@RequestMapping怎样工作的呢?Spring怎样正确调用controller来处理请求呢?等等,后面的文章我们一一解答。
相关文章推荐
- eclipse主题颜色配置
- Spring MVC 解读——<mvc:annotation-driven/>
- 10.03JAVA应用学习知识点
- java中匿名内部类的使用
- Java多线程实验
- Spring DI 继承
- Windows下搭建Eclipse+Android4.0开发环境
- Java对象在JVM中的生命周期
- java中的基本语法
- 如何快速构建基于Spring4.0的Rest API(攻略)
- java读取Excel文件
- Spring3.2新注解@ControllerAdvice
- Spring 用注解实现IOC控制反转
- Java 数组
- Java设计模式之代理模式
- Java高级1
- [java学习笔记]java语言基础概述之运算符&程序流程控制&for循环嵌套
- GeoHash解析及java实现
- MyEclipse 2014 破解图文详细教程
- Java设计模式之策略模式与状态模式