大家熟知的springMVC的工作流程,用户发送请求到dispatchservlet,也就是我们说的springMVC的中央控制器。我们需要把dispatchservlet配置到我们web工程的web.xml中并且加载顺序为第一位<load-on-startup>1</load-on-startup>。dispatchservlet其实就是springMVC的入口。
dispatchservlet里面没有我们所熟知的init的方法。DispatcherServlet extends FrameworkServlet我们去寻找它的父类,在FrameworkServlet中也没有找到init的方法。FrameworkServlet extends HttpServletBean我们去寻找它的父类,在HttpServletBean中我们可以看到它继承的是HttpServlet,并且找到了init方法,该init方法被final所修饰,说明这个方法是不可以被子类重写的 。 HttpServlet这个类 继承GenericServlet,GenericServlet 实现了 Servlet接口,servlet 是一个接口没有具体实现, 而GenericServlet 中init () 是一个空方法 HttpServlet没有实现init 说明是继承了父类的, 那么 就只有HttpServletBean这个方法有。我们所说本质上dispatchservlet就是一个Servlet。
在HttpServletBean中的init()中描述:判断日志级别,打印Initializing Spring FrameworkServlet 'springServlet'。 getServletName()指的就是web.xml中配置dispatchservlet的<servlet-name>springServlet</servlet-name>,下面就是一些对spring的属性、配置文件的包装。重点是它的initServletBean()的方法,是在子类FrameworkServlet中实现的
在FrameworkServlet中的initServletBean()描述:首先是它的一些日志的打印,主要是执行的initWebApplicationContext()和initFrameworkServlet()这两个方法,第二个是一个空方法,我们只需要关注initWebApplicationContext()这个方法就可以了。
在FrameworkServlet中的initWebApplicationContext()主要configureAndRefreshWebApplicationContext(cwac)这个方法。在这个方法中,我们把前面new的上下文、servlet的配置、命名空间放入wac中,然后就是它的wac.refresh()。
在AbstractApplicationContext中的refresh(),主要是ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();做了xml的解析和annotation的支持。首先我们先来研究一下第一个方法refreshBeanFactory()字面意思就是刷新bean工厂方法,点进去AbstractRefreshableApplicationContext》》refreshBeanFactory(),判断是否存在BeanFactory(),如果存在就销毁,关闭BeanFactory(),这种写法算是一个保险的机制,更加全面。DefaultListableBeanFactory beanFactory = createBeanFactory()实例化ListableBeanFactory,loadBeanDefinitions(beanFactory)解析xml装载成BeanDefinition对象,点进去XmlWebApplicationContext》》loadBeanDefinitions(DefaultListableBeanFactory beanFactory)通过XmlBeanDefinitionReader加载和定义bean,beanDefinitionReader.setEnvironment(getEnvironment())设置standardEnvironment,beanDefinitionReader.setResourceLoader(this),这个this因为底层继承的是DefaultResourceLoader,所以这不会报类型错误,主要还是看loadBeanDefinitions(beanDefinitionReader)解析spring配置的XXXXaplication.xml,具体执行AbstractBeanDefinitionReader.loadBeanDefinitions()。loadBeanDefinitions(beanDefinitionReader)》》reader.loadBeanDefinitions(configLocation)把xml读取进来,并且循环加载》》loadBeanDefinitions(location, null)》》loadBeanDefinitions(resources)是把配置的applicationContext文件变为resources,相当于io流的读取操作,counter += loadBeanDefinitions(resource)循环加载这个resource》》XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource)(spring的配置我们可以写成proper的文件,也可以写成xml的文件,新版本的又新加了一个Groovy,我还没用过)》》loadBeanDefinitions(new EncodedResource(resource))》》
try {
InputStream inputStream = encodedResource.getResource().getInputStream();//读取io操作
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());//加载
BeanDefinition,点进去
}finally {inputStream.close();}}》》
try {
Document doc = doLoadDocument(inputSource, resource);//变成document对象
return registerBeanDefinitions(doc, resource);//注册这个beandefinition
}
》》
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//创建
documentReader
documentReader.setEnvironment(getEnvironment());int countBefore = getRegistry().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//注册进去。点进去return getRegistry().getBeanDefinitionCount() - countBefore;
》》doRegisterBeanDefinitions(root)》》parseBeanDefinitions(root, this.delegate)》》parseDefaultElement(ele, delegate)解析默认元素的,delegate.parseCustomElement(ele)解析自定义元素的,我们今天只关注默认元素的解析》》点进去parseDefaultElement(ele, delegate)我们可以看见默认的4个元素,import,alias,bean,ele,我们关注一下bean的解析》》
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
解析:BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); 1、对Element 属性getAttribute("id"/"name") 2、对获得id/name 赋值给GenericBeanDefinition对象它实现AbstractBeanDefinition-->BeanDefinition接口 (AbstractBeanDefinition对象就是保存解析的bean 属性 并对默认属性赋值 id/name/scope/lazyInit/beanClass
/initMethodName/propertyValues......) 方法:AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, conta
iningBean); 3、构造返回 new BeanDefinitionHolder(beanDefinition,beanName,aliasesArray) 里面就是beanName、 aliasesArray、beanDefinition(对象) 方便后面spring 依赖注入直接通过beanName/aliasesArray(别名)
获取beanDefinition对象。 解析:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry() 1、获取bdHolder的beanName和BeanDefinition 对象 2、将BeanDefinitionRegistry----》registerBeanDefinition(beanName,
definitionHolder.getBeanDefinition() ); 3、将beanName 添加到List<String>,将beanName--key和beanDefinition--value 保存到
Map<String, BeanDefinition> 中。