本文从直接调用的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创建父级容器
实际调用的是
public AbstractApplicationContext(ApplicationContext 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):将传入的配置文件转换为容器的配置文件。
这步比较简单,只是一个简单的设值操作。
public void setConfigLocations(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++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
2.3 refresh():这一步是真正的创建容器加载bean
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//这步无关紧要,就是设置一下开始刷新时间,开始记录日志,检查是否运行时环境变量是完整的
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
1.beanFactory是否存在,存在就销毁:destroyBeans();
2.根据父级beanFactory创建一个新的beanFactory:createBeanFactory();
3.定制当前的beanFactory(主要是设置对注解的支持):customizeBeanFactory(beanFactory);
4.加载XmlBeanDefinitionReader:loadBeanDefinitions(beanFactory);
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
1.为beanFactory加载一个ContextClassLoader:beanFactory.setBeanClassLoader(getClassLoader());
2.加载一个BeanExpressionResolver去解析spring的el表达式例如#{}:beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
3.加载一个资源加载器ResourceLoader加载classpath以及一些file资源,加载一个PropertyResolver,去获取一些属性文件信
息:beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
4.加载一个BeanPostProcessor,这个处理器提供两个回调方法给spring创建bean的过程中回调。书面上交spring扩展
点:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
5.最后是注册一些环境变量。
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
在ApplicationContext初始化后,修改context的
beanFactory
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
在单例应用bean之前实例化所有的
BeanFactoryPostProcessor并调用
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
在实例化应用bean之前实例化所有的
BeanFactoryPostProcessor并调用
// Initialize message source for this context.
initMessageSource();
使用父级messageSource初始化本context国际化组件,如果父级没有,创建一个新的
beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
使用实例化一个在context自定义的时间广播器,如果没有自定义的用默认的SimpleApplicationEventMulticaster
// 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;
}
}
}
3.IOC相关类说明
至此,bean已经实例化完毕。更多细节参考:
http://www.iteye.com/topic/1122859