zoukankan      html  css  js  c++  java
  • web中spring框架启动流程第一发

    web.xml中springmvc相关配置如下:
    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>

    首先是tomcat容器启动,然后在容器初始化servlet时,会对DispatcherServlet类进行实例化,进行代码分析,查看DispatchcherServlet的类图如下:

    可以看到,DispatcherServlet是符合servlet规范的,可以被tomcat容器作为servlet管理;需要注意的是上述类图中HttpServletBean类中的init()方法,该方法方法体如下图:

    该方法是同servlet的生命周期相关的,在后续DispatcherServlet初始化过程中会被调用,其中的bw.setPropertyValues(pvs,true)方法用于将DispatcherServlet中的参数设置到servlet中,便于后续

    读取spring的所有配置文件,如下图,但是this.initServletBean才是个重要的调用,因为在此之后才开始进行spring上下文的初始化工作

    this.initServletBean最终调用到了FrameworkServlet类中的覆盖方法,在该覆盖方法中首先是创建WebApplicationContext对象,最终,在FrameworkServlet类的createWebApplicationContext方法中

    发现创建了一个XmlWebApplicationContext类型的spring上下文对象,关键代码如下图:

    需要注意在上下文对象创建之后,会对上下文进行初始化,这个调用是在configureAndRefreshWebApplicationContext(wac)开始的,流程如下图:

    由 上图可以看到在对于spring上下文进行一系列的配置之后,最终调用了refresh()方法,开始真正的进行上下文的初始化工作;

    因为wac是一个XmlWebApplicationContext对象实例,查看其类图如下:

    在调用wac.refresh()方法后,最终进入到AbstractApplicationContext类的refresh方法中进行上下文的初始化,其核心代码如下:

    关键部分为beanFactory的创建,这个是用来管理bean的,可谓是相当重要,可以把ApplicationContext作为一个门面,而beanFactory是内核,一个主外,一个主内,对外的部分主要提供

    了对于单例bean的访问的各种接口,beanFactory则像勤劳的幕后工作者一样处理bean的注册等等幕后事宜;竖线部分是一个模板流程,使用了模板模式,很多方法只提供了空实现,需要

    子类去根据实际需要进行相应的行为,比心的一行比较重要,这块是ApplicationContext和beanFactory进行关联的地方;

    在执行ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();之后,最终调用到AbstractRefreshableApplicationContext的refreshBeanFactory方法,其代码如下:

    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    可以看到,最终创建了DefaultListableBeanFactory实例;在beanFactory创建过程中,首先是判断是否存在,存在则销毁再创建,否则直接创建,圈圈圈住的两行比较重要,其中第一行表示

    对于beanFactory进行设定,如允许bean定义覆盖或者循环引用;第二行则是加载bean定义,从配置文件、注解等等地方加载bean,执行该行后,最终调用到XmlWebApplicationContext中

    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);执行后将beanFactory注册到AbstractBeanDefinitionReader
    实例中,后续是beanDefinitionReader的一些设置工作,最后一行进行bean定义加载,执行后

    首先是获取要读取的文件路径,然后进行遍历读取,最终调用到AbstractBeanDefinitionReader类的loadBeanDefinitions方法中,核心代码如下

    首先之前XmlWebApplicationContext反向将自身注册到reader中的资源加载器,然后通过资源加载器加载资源并进行bean的读取

     经过一系列的调用,最终在XmlBeanDefinitionReader的doLoadBeanDefinitions方法中真正的进行bean定义加载,如下图:

    该方法内部,首先对于xml文件进行加载,然后就是进行解析,注册beanDefinition,如下图:

    在执行registerBeanDefinitions之后调用到XmlBeanDefinitionReader的registerBeanDefinitions方法,方法体如下:

    其中getRegistry()方法获取了之前注入的DefaultListableDeanFactory,开始方法后

    最终调用到DefaultBeanDefinitionDocumentReader的parseBeanDefinitions

    其中parseDefaultElement方法用于处理默认的标签,而parseCustomElement用于处理自定义的标签,这块内容感兴趣的话可以研究下那个xml自定义标签的解析,这个在分布式rpc框架等等支持xml文件配置方式的工程中可以见到自定义
    标签的解析过程,上图代码部分主要是xml解析,beanDefinition注册,其过程十分类似,在此不再赘述。
    整个beanDefinition注册完成后,整个调用回到AbstractRefreshableApplicationContext的refreshBeanFactory中并完成beanFactory和ApplicationContext的关联,即前面我所说的一个主内一个主外,如下图所示:

    最终回到AbstractApplicationContext的refresh方法中;

    至此,beanFactory获取算是完结了,整个过程是不是一气呵成,是不是很爽,但是这仅仅是模板方法的一部分,下面还有很多,下次再战

     在此,总结下整个流程:

    首先是tomcat容器启动,实例化servlet,DispatcherServlet被实例化,之后伴随servlet生命周期方法调用,DispatcherServlet的init方法调用,进行ApplicationContext的实例化

    和初始化refresh,在初始化的过程中,进行DefaultListableBeanFactory的实例化、初始化、xml解析,beanDefinition的注册,最后BeanFactory注册到Application中,这整个

    过程完结,模板方法第一个调用完成,,,



  • 相关阅读:
    近段时间学习html和CSS的一些细碎总结
    循环队列
    【IOS】IOS高速入门之OC语法
    2014华为机试-字符串替换
    自己动手写操作系统--个人实践
    HBase学习(十四)LINUX下用Eclipse构建HBase开发环境
    IOS成长之路-Nsstring中搜索方法rangeOfString
    Java JDBC连接SQL Server2005错误:通过port 1433 连接到主机 localhost 的 TCP/IP 连接失败
    java 不同意同一账户不同IP 同一时候登录系统解决的方法 兼容IE Firefox
    十二.200多万元得到的创业教训--app名字是关键
  • 原文地址:https://www.cnblogs.com/lxk2010012997/p/9310084.html
Copyright © 2011-2022 走看看