栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Spring源码第二天】ApplicationContext源码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Spring源码第二天】ApplicationContext源码

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

从源码理解Bean的生命周期
    • 1. 扫描配置文件
    • 2. refresh()方法
      • 2.1 prepareRefresh()
      • 2.2 obtainFreshBeanFactory()
      • 2.3 prepareBeanFactory
      • 2.4 postProcessBeanFactory
      • 2.5 bean实例化前的准备
      • 2.6 finishBeanFactoryInitialization(重要)
    • 总结


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 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的方法等;

  1. refresh方法执行逻辑
  2. 实例化对象的执行流程

    今天的结果是用过浏览源码理解Bean的具体声明周期,走了一遍调用流程;还有很多细节没看,如:
  • 三级缓存解决循环依赖
  • populate的内部实现
  • 暴露对象的意义
  • FactorBean的引入,在实例化对象后的最后getObject方法的含义
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/860603.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号