Spring源码解析(三)

76 阅读2分钟

ClassPathXmlApplicationContext源码详解

ClassPathXmlApplicationContext构造方法是Spring初始化的入口,从源码中可以看出,主要做了三件事:

  1. 创建ClassPathXmlApplicationContext父类对象,初始化一些准备条件
  2. 设置配置文件路径
  3. 调用refresh方法
// ClassPathXmlApplicationContext的构造方法
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
    //创建父类对象,初始化一些准备条件
    super(parent);
    //设置配置文件路径
    this.setConfigLocations(configLocations);
    if (refresh) {
        this.refresh();
    }
}

ClassPathXmlApplicationContext父类对象创建时,初始化的准备条件

ClassPathXmlApplicationContext父类是AbstractApplicationContext,其构造方法中做了一系列的操作:

  1. this.logger = LogFactory.getLog(this.getClass()):获取当前类的日志记录器
  2. this.id = ObjectUtils.identityToString(this):生成当前对象的唯一ID
  3. this.displayName = ObjectUtils.identityToString(this):生成当前对象的唯一标识字符串
  4. this.beanFactoryPostProcessors = new ArrayList():初始化一个空的列表,用于存储 BeanFactory 后处理器
  5. this.active = new AtomicBoolean():使用原子布尔值,表示对象的活跃状态
  6. this.closed = new AtomicBoolean():使用原子布尔值,表示对象是否已关闭
  7. this.startupShutdownLock = new ReentrantLock():创建一个可重入锁,用于控制启动和关闭过程的同步
  8. this.applicationStartup = ApplicationStartup.DEFAULT:设置默认的应用启动跟踪
  9. this.applicationListeners = new LinkedHashSet():初始化一个有序集合,用于存储应用程序监听器
  10. this.resourcePatternResolver = this.getResourcePatternResolver():获取资源模式解析器
public AbstractApplicationContext() {
    this.logger = LogFactory.getLog(this.getClass());
    this.id = ObjectUtils.identityToString(this);
    this.displayName = ObjectUtils.identityToString(this);
    this.beanFactoryPostProcessors = new ArrayList();
    this.active = new AtomicBoolean();
    this.closed = new AtomicBoolean();
    this.startupShutdownLock = new ReentrantLock();
    this.applicationStartup = ApplicationStartup.DEFAULT;
    this.applicationListeners = new LinkedHashSet();
    this.resourcePatternResolver = this.getResourcePatternResolver();
}

setConfigLocations方法

public void setConfigLocations(@Nullable String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];

        for(int i = 0; i < locations.length; ++i) {
            //调用resolvePath方法对xml文件进行解析
            this.configLocations[i] = this.resolvePath(locations[i]).trim();
        }
    } else {
        this.configLocations = null;
    }
}

resolvePath方法

protected String resolvePath(String path) {
    //getEnvironment方法是获取操作系统环境变量和JVM虚拟机环境变量
    return this.getEnvironment().resolveRequiredPlaceholders(path);
}

getEnvironment方法

public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
        //创建Environment对象
        this.environment = this.createEnvironment();
    }

    return this.environment;
}

在执行createEnvironment方法中,会创建StandardEnvironment对象,调用的是其无参构造方法

public StandardEnvironment() {
    //内部没有代码
}

StandardEnvironment的无参构造方法中没有代码,于是去其父类的构造方法中,发现最后调用的是StandardEnvironment中的customizePropertySources方法

protected AbstractEnvironment(MutablePropertySources propertySources) {
   this.propertySources = propertySources;
   this.propertyResolver = createPropertyResolver(propertySources);
   //调用了StandardEnvironment中的customizePropertySources方法
   customizePropertySources(propertySources);
}
protected void customizePropertySources(MutablePropertySources propertySources) {
   propertySources.addLast(
         new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
   propertySources.addLast(
         new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

customizePropertySources方法中,getSystemProperties方法获取的是java虚拟机系统属性,例如:系统的 Java 版本、操作系统名称、用户的主目录等。而getSystemEnvironment方法获取的是操作系统属性,例如:环境变量中的PATH信息、java安装路径、登录用户名、可执行文件路径、操作系统名称等

getSystemProperties方法:

系统属性.jpg

getSystemEnvironment方法:

环境变量.jpg