/**
* Ioc 容器源码分析基础案例
*/
@Test
public void testIoC() {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("classpath:applicationContext.xml");
LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
System.out.println(lagouBean);
}
我们以 ClasspathXmlApplicationContext 为例,深⼊源码分析:
一. 分析 Bean 的创建是在容器初始化时还是在 getBean 时
根据断点调试,我们发现,在未设置延迟加载的前提下,Bean 的创建是在容器初始化过程中完成的。
二. 分析构造函数调⽤情况
通过如上观察,我们发现构造函数的调⽤时机在AbstractApplicationContext类refresh⽅法的
finishBeanFactoryInitialization(beanFactory)处;
三. 分析 InitializingBean 之 afterPropertiesSet 初始化⽅法调⽤情况
观察调⽤栈
通过如上观察,我们发现 InitializingBean中afterPropertiesSet ⽅法的调⽤时机也是在
AbstractApplicationContext类refresh⽅法的finishBeanFactoryInitialization(beanFactory);
四. 分析BeanFactoryPostProcessor 初始化和调⽤情况
分别在构造函数、postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现
BeanFactoryPostProcessor 初始化在AbstractApplicationContext类refresh⽅法的
invokeBeanFactoryPostProcessors(beanFactory);
postProcessBeanFactory 调⽤在AbstractApplicationContext类refresh⽅法的
invokeBeanFactoryPostProcessors(beanFactory);
五. 分析 BeanPostProcessor 初始化和调⽤情况
分别在构造函数、postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现
BeanPostProcessor 初始化在AbstractApplicationContext类refresh⽅法的
registerBeanPostProcessors(beanFactory);
postProcessBeforeInitialization 调⽤在AbstractApplicationContext类refresh⽅法的
finishBeanFactoryInitialization(beanFactory);
postProcessAfterInitialization 调⽤在AbstractApplicationContext类refresh⽅法的
finishBeanFactoryInitialization(beanFactory);
六. 总结
根据上⾯的调试分析,我们发现 Bean对象创建的⼏个关键时机点代码层级的调⽤都在
AbstractApplicationContext 类 的 refresh ⽅法中,可⻅这个⽅法对于Spring IoC 容器初始化来说相当关键,汇总如下:
关键点 | 触发代码 |
构造器 | refresh#finishBeanFactoryInitialization(beanFactory)(beanFactory) |
BeanFactoryPostProcessor 初始化 | refresh#invokeBeanFactoryPostProcessors(beanFactory) |
BeanFactoryPostProcessor ⽅法调⽤ | refresh#invokeBeanFactoryPostProcessors(beanFactory) |
BeanPostProcessor 初始化 | registerBeanPostProcessors(beanFactory) |
BeanPostProcessor ⽅法调⽤ | refresh#finishBeanFactoryInitialization(beanFactory) |