ClassPathXmlApplicationContext源码详解
ClassPathXmlApplicationContext构造方法是Spring初始化的入口,从源码中可以看出,主要做了三件事:
- 创建ClassPathXmlApplicationContext父类对象,初始化一些准备条件
- 设置配置文件路径
- 调用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,其构造方法中做了一系列的操作:
- this.logger = LogFactory.getLog(this.getClass()):获取当前类的日志记录器
- this.id = ObjectUtils.identityToString(this):生成当前对象的唯一ID
- this.displayName = ObjectUtils.identityToString(this):生成当前对象的唯一标识字符串
- this.beanFactoryPostProcessors = new ArrayList():初始化一个空的列表,用于存储 BeanFactory 后处理器
- this.active = new AtomicBoolean():使用原子布尔值,表示对象的活跃状态
- this.closed = new AtomicBoolean():使用原子布尔值,表示对象是否已关闭
- this.startupShutdownLock = new ReentrantLock():创建一个可重入锁,用于控制启动和关闭过程的同步
- this.applicationStartup = ApplicationStartup.DEFAULT:设置默认的应用启动跟踪
- this.applicationListeners = new LinkedHashSet():初始化一个有序集合,用于存储应用程序监听器
- 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方法:
getSystemEnvironment方法: