提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
从源码理解Bean的生命周期
spring源码阅读第一天
在理解大致Bean生命周期后,继续从源码层面去了解整个流程;很常规的:最重要的就是AbstractApplicationContext中的refresh方法;
源码阅读入口,debug调试:
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
1. 扫描配置文件
可以走进ClassPathXmlApplicationContext的构造方法:
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent); // 调用父类的构造创建一个Xml的容器
setConfigLocations(configLocations); // 设置配置文件路径
if (refresh) {
refresh(); // 核心方法
}
}
2. refresh()方法
之后就可以进入 refresh()方法,通过14个方法调用完成整个bean的创建流程,整个方法的执行对于各阶段来说可以分为:准备 -》 创建
2.1 prepareRefresh()
进行刷新前的准备工作,项目启动的环境:
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// ... 日志打印
// Initialize any placeholder property sources in the context environment.
// 空实现,由子类实现
initPropertySources();
// 获取系统环境 new StandardEnvironment();
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 添加事件集
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2.2 obtainFreshBeanFactory()
看名字就是获取一个beanFactory工厂;想想bean的生命周期,BeanFactory是整个流程的入口,因此需要提前创建:
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) { // 如果有工厂销毁,关闭
destroyBeans();
closeBeanFactory();
}
// 创建一个新的工厂,然后获取
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为beanFactory设置一些基本属性
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory); // 加载beanDefinition对象
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
结束后:
这里看beanFactory的实现类是DefaultListenedBeanFactory, 下面是他的继承关系图:
2.3 prepareBeanFactory
工厂创建结束后,BeanDefinition对象也有了,下一步就应该注入bean工厂,但是想想生命周期,还有一个beanFactoryPostProcessor增强的过程,因此过程如下:
这里的忽略Aware,前面说过Aware出现在实例化阶段,那么说明对象已经创建完毕了;而在当前方法的作用是用来操作BeanDefinition的,因此需要忽略Aware; 否则对象创建完了,修改BeanDefinition也没什么意义。
2.4 postProcessBeanFactory
空实现,由子类完成;想想实现BeanFactoryPostProcess中的重写方法就是这个 spring源码阅读第一天
2.5 bean实例化前的准备
2.6 finishBeanFactoryInitialization(重要)
开始进行实例化:
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
进入preInstantiateSingletons 方法:
// 封装bean信息成一个集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 合并父子容器的beanDefinition信息,之前创建的BeanDefinition是Generic类型的
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断是不是FactoryBean,即是否为可自己暴露的工厂
if (isFactoryBean(beanName)) {
// ...
else {
getBean(beanName);
}
在调用doGetBean的时候,首先getSingleton先查看缓存
可以先有个印象,spring中存在三级缓存,用来解决循环依赖问题
对于doGetBean的部分操作之前写过一次(仅针对无参构造bean的注入)
对于概览可以先看一下:Spring Bean的无参构造过程
继续浏览到:
doCreateBean中包含:createBeanInstance和populate
接着看到结尾:return BeanUtils.instantiateClass(constructorToUse);
使用反射机制获取无参构造然后创建了bean对象;当然还有很多操作:如循环依赖,是否提前暴露;先有个印象;
使用无参构造的bean中的属性使用默认值,因此有了后面的populate填充属性。
填充属性后,还有一个方法调用,点进去
总结
至此,普通的bean对象已经创建完成,可返回了;如果使用了FactoryBean,应该还有getObject的方法等;
- refresh方法执行逻辑
- 实例化对象的执行流程
今天的结果是用过浏览源码理解Bean的具体声明周期,走了一遍调用流程;还有很多细节没看,如:
- 三级缓存解决循环依赖
- populate的内部实现
- 暴露对象的意义
- FactorBean的引入,在实例化对象后的最后getObject方法的含义