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初始化的基本流程框架,后面几篇将陆续对其中每一个方法进行详细的分析
  • 相关阅读:
    ffmpeg rtmp推流 视频转码
    java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
    nginx stream 流转发,可以转发rtmp、mysql访问流,转发rtmp、jdbc请求
    java web http 转https 通过nginx代理访问
    linux 服务器磁盘挂载
    novnc 通过websockify代理 配置多点访问
    linux 文件服务 minio 安装部署配置
    AOP实现原理,手写aop
    java 泛型
    JAVA反射getGenericSuperclass()用法
  • 原文地址:https://www.cnblogs.com/tangpu/p/3203890.html
Copyright © 2011-2022 走看看