本文从直接调用的ClassPathXmlApplicationContext开始说起,看看spring是怎么实现IOC/DI
1.spring应用代码
其中singer.xml是自定义的
DIMp3类是自定义的。
public static void main(String[] args) {
//spring通过应用上下文装载bean的定义并组装
//使用spring实现的ClassPathXmlApplicationContext加载配置文件
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext("singer.xml");
//从应用上下文中获取bean
DIMp3 mp3 = (DIMp3) context.getBean("mp3");
mp3.play();
}
2.ClassPathXmlApplicationContext:获取容器
ClassPathXmlApplicationContext("singer.xml"); 实际调用的是
/**
* 使用configLocations指定配置文件去构造一个spring容器
* refresh是否刷新容器,默认true(具体的刷新后面讲解)
* parent: 当前容器父级容器
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
2.1 super(parent):给定parent创建父级容器
this.resourcePatternResolver = getResourcePatternResolver();//返回一个PathMatchingResourcePatternResolver对象
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}//将父级容器运行时环境合并到当前容器运行时环境。
}
2.2 setConfigLocations(configLocations):将传入的配置文件转换为容器的配置文件。
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++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
2.3 refresh():这一步是真正的创建容器加载bean
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}