zoukankan      html  css  js  c++  java
  • spring源码学习笔记-初始化(一)-概览

     

    spring源码学习笔记-初始化(一)-概览

     

    转自http://www.sandzhang.com/blog/2011/03/30/spring-study-notes-initialization-1/

    版本:spring-framework-3.0.5.RELEASE
     
    很多人看开源框架源代码的时候都不知道从哪里入手,我这里推荐一个最简单的办法,写一个最简单的应用的例子,然后根据这个应用一点一点查看在源码中的运行步骤,这样就能对框架有一个基本的了解,有了这个基本的认识,再去针对不同模块扩展开来仔细研究。
     
    本系列主要是学习spring的源码,首先是最简单的使用例子:
    [java] view plaincopy
     
    1. ApplicationContext ctx = new ClassPathXmlApplicationContext(  
    2.                 "spring-config.xml");  
    3. FooService foo = (FooService) ctx.getBean("FooService");  

    我们看第一行初始化了一个ClassPathXmlApplicationContext对象,

    注:也可以用FileSystemXmlApplicationContext来加载,两者的区别只是查找配置文件的起始路径不同,一个以classpath为当前路径,一个是直接用文件系统的当前路径,内部没有太大区别。

    注2:web工程大家都知道我们配置了ContextLoaderListener,这里暂时不做介绍,后面会有专门的分析,起始主题流程都差不多,详情请参见:从源码看Spring在web工程中的初始化。

    请看下面的构造方法,参数是spring配置文件在classpath中的全路径名:


    [java] view plaincopy
     
    1. public ClassPathXmlApplicationContext(String configLocation) throws BeansException {  
    2.     this(new String[] {configLocation}, truenull);  
    3. }  

    可以看到里面调用了另外一个构造方法(如下),其中传递了两个默认参数refresh=true立即刷新,parent=null继承为空,并且把配置文件封装为了一个String数组,这里主要是因为spring是支持多个配置文件的
    [java] view plaincopy
     
    1. public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)  
    2.             throws BeansException {  
    3.    
    4.     super(parent);  
    5.     setConfigLocations(configLocations);  
    6.     if (refresh) {  
    7.         refresh();  
    8.     }  
    9. }  

    我们看这个构造方法的代码:

    • 首先调用了父类的构造函数
    • 调用setConfigLocations设置配置文件位置信息(代码如下)
    • 判断如果refresh为true则调用refresh()方法,refresh方法在AbstractApplicationContext中

    setConfigLocations代码:
    很简单,主要是检验是否传入参数为空然后赋值给configLocations属性,不过其中有两个小特点可以注意一下:

    1. 并没有直接把传入参数locations直接赋值给属性,而是new了一个String数组,然后循环赋值,这里主要是出于安全考虑避免外面传入的字符串数组变化影响spring内部
    2. 可以看到赋值前有调用了一下resolvePath方法,这个方法实现了一些系统变量的替换,例如路径里可以使用${}加载系统变量值
    [java] view plaincopy
     
    1. public void setConfigLocations(String[] locations) {  
    2.     if (locations != null) {  
    3.         Assert.noNullElements(locations,  
    4.                 "Config locations must not be null");  
    5.         this.configLocations = new String[locations.length];  
    6.         for (int i = 0; i < locations.length; i++) {  
    7.             this.configLocations[i] = resolvePath(locations[i]).trim();  
    8.         }  
    9.     } else {  
    10.         this.configLocations = null;  
    11.     }  
    12. }  

    下面看refresh刷新方法,这个刷新方法主要是从配置文件加载bean配置的过程,代码如下:
    [java] view plaincopy
     
    1. public void refresh() throws BeansException, IllegalStateException {  
    2.     // 整个刷新过程是同步的  
    3.     synchronized (this.startupShutdownMonitor) {  
    4.         // 刷新前的准备工作  
    5.         prepareRefresh();  
    6.         // 关闭释放旧的beanFactory创建新的beanFactory,读取配置文件等  
    7.         ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
    8.         // 对beanFactory进行一些基本的初始化  
    9.         prepareBeanFactory(beanFactory);  
    10.    
    11.         try {  
    12.             // 下面两行主要用户扩展,处理所有已注册的BeanFactoryPostProcessor,实现在已经加载配置但未初始化bean时对配置进行修改  
    13.             postProcessBeanFactory(beanFactory);  
    14.             invokeBeanFactoryPostProcessors(beanFactory);  
    15.             // 处理所有已注册的BeanPostProcessor,主要用于扩展,实现bean初始化前后的一些定制操作  
    16.             registerBeanPostProcessors(beanFactory);  
    17.    
    18.             // 初始化消息源bean  
    19.             initMessageSource();  
    20.             // 初始化事件监听器集,也有人叫事件监听器的注册表,所有的事件监听器都在这个bean里进行管理  
    21.             initApplicationEventMulticaster();  
    22.             // 主要用于扩展,实现一些特殊bean的初始化,时间点是类似消息源事件监听器集等特殊bean初始化后,普通的bean初始化前  
    23.             onRefresh();  
    24.             // 注册监听器  
    25.             registerListeners();  
    26.             // 初始化其余的非延迟加载的单例bean  
    27.             finishBeanFactoryInitialization(beanFactory);  
    28.    
    29.             // 刷新完成调用LifecycleProcessor的onRefresh方法,并且发布ContextRefreshedEvent事件  
    30.             finishRefresh();  
    31.         } catch (BeansException ex) {  
    32.             // 销毁已经创建的单例bean  
    33.             destroyBeans();  
    34.             // 重新设置active标记  
    35.         cancelRefresh(ex);  
    36.             throw ex;  
    37.         }  
    38.     }  
    39. }  

    上面是一个spring初始化的基本流程框架,后面几篇将陆续对其中每一个方法进行详细的分析
  • 相关阅读:
    Asp.net操作Excel----NPOI
    Python第一模块
    Sping笔记一览
    IO流技术一览
    事务技术一览
    日常问题记录
    分页与JDBC显示文档。
    分页技术与JDBC一览
    JDBC 技术开发
    MYSQL
  • 原文地址:https://www.cnblogs.com/tangpu/p/3203890.html
Copyright © 2011-2022 走看看