先看一个简单的程序:
package com.shadow;
import com.shadow.framework.DataSourceConfig;
import com.shadow.framework.OwnClassPathXmlApplicationContext;
import com.shadow.model.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Map;
public class TestIoc {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new OwnClassPathXmlApplicationContext("spring.bean.xml");
User user =(User) ac.getBean("user");
System.out.println(user);
Map<String, Object> systemProperties = ac.getEnvironment().getSystemProperties();
for (Map.Entry<String, Object> stringObjectEntry : systemProperties.entrySet()) {
if("spring5.0".equalsIgnoreCase(stringObjectEntry.getKey())){
System.out.println("key:"+stringObjectEntry.getKey());
System.out.println("value:"+stringObjectEntry.getValue());
}
}
System.out.println("*******************");
DataSourceConfig dataSourceConfig =(DataSourceConfig) ac.getBean("dataSourceConfig");
System.out.println(dataSourceConfig.getUserName());
System.out.println(dataSourceConfig.getPassWord());
System.out.println(dataSourceConfig.getUrl());
}
}
从OwnClassPathXmlApplicationContext构造方法说起。具体代码如下。不难发现有参构造中调用了父类ClassPathXmlApplicationContext的构造方法,然后this函数又调用了本类的有参构造。具体三段代码如下。
重点看下setConfigLocations方法,目的设置应用上下文的配置路径,
然后看下AbstractRefreshableConfigApplicationContext父类中resolvePath方法。
由生出的getEnvironment方法生成一个StandardEnvironment ,
发现重写了父类AbstractEnvironment中的customizePropertySources方法。获取到了 当前JVM 设置的属性值, Java进程变量。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2cc649f713fe4851acb075685f95d869.png
紧接着进入resolveRequiredPlaceholders()方法
strictHelper为空,new一个PropertyPlaceholderHelper,进入PropertyPlaceholderHelper构造方法。
然后调用doResolvePlaceholders方法,在
继续调用replacePlaceholders方法
在进入parseStringValue方法,因为我的配置文件不包含$缀,这里直接返回了。
再看refresh()方法,调用父类AbstractApplicationContext中refresh()方法
第一个方法:prepareRefresh
protected void prepareRefresh() {
// 当前启动时间戳
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
初始化上下文环境中的任何占位符属性资源
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
验证标记为"必须"的所有属性是否可以解析
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
//初始化或者重置earlyApplicationListeners
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
第二个方法:obtainFreshBeanFactory 返回默认的DefaultListableBeanFactory
customizeBeanFactory自定义beanFactory ,包括是否允许定义bean名称覆盖,以及循环引用。
loadBeanDefinitions