Spring ioc容器是什么时候创建的

缘起

一直说Spring ioc容器,但是它是什么时候创建的呢? 且听我慢慢道来.

分析

debug用的demo是【1】.

首先进到我们的老朋友——refresh方法中去

org.springframework.context.support.AbstractApplicationContext.refresh()

1
2
3
4
5
6
7
8
9
@Override
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

注意第8行就获取了我们的ioc容器——beanFactory.

然后后面不论是进行我们熟知的 invokeBeanFactoryPostProcessors还是registerBeanPostProcessors还是finishBeanFactoryInitialization,都带上了它.

跟进源码1的第8行

org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory()

1
2
3
4
5
6
7
8
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

​ 源码2

跟进源码2的第2行

org.springframework.context.support.GenericApplicationContext.refreshBeanFactory()

1
2
3
4
5
6
7
8
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}

​ 源码3

而beanFactory是作为GenericApplicationContext的属性的. 但是AnnotationConfigApplicationContext是GenericApplicationContext的子类,所以父类的构造器也会被执行. 看看GenericApplicationContext的构造器

1
2
3
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}

是直接new出来的. 也就是说我们在main方法中写下

1
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

的时候,就已经初始化AnnotationConfigApplicationContext的父类GenericApplicationContext,而在GenericApplicationContext 中就初始化了beanFactory,亦即ioc容器.

所以我们就明白了Spring IOC 容器是什么时候产生的了.

DEMO

【1】https://github.com/yfsyfs/backend/tree/master/spring-annotation-condition