Spring源码阅读 -- > SpringIOC初始化流程

1、Spring源码环境搭建参照

spring-framework-5.1.x 源码编译 环境搭建 [ idea:2020.1 ]_chuanchengdabing的博客-CSDN博客spring-framework-5.1.x 源码编译 环境搭建 [ idea:2020.3.1 ]一. Gradle下载与安装二. 下载spring源码GitHub 搜索springframework 版本号 5.1.x三. idea导入spring源码build.gradlerepositories {maven { url “https://maven.aliyun.com/repository/spring-plugin” }maven { url “https://https://blog.csdn.net/chuanchengdabing/article/details/115330718?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164536768016780265454457%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164536768016780265454457&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-6-115330718.nonecase&utm_term=Spring%E6%BA%90%E7%A0%81&spm=1018.2226.3001.4450

2、 IoC容器体系

        IoC是Spring的核心模块,抽象了对象管理、依赖关系管理的框架解决方案。Spring提供了很多的容器,其中BeanFactory是顶层容器(根容器),不能被实例化,它定义了所有IoC容器必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如经常用到的ApplicationContext,其下更具体的实现如ClassPathXmlApplicationContext包含了解析XML的等内容,AnnotationConfigApplicationContextze则是包含了注解解析等一系列的内容。这也表示SpringIoC容器继承体系非常灵活,需要使用哪个层次就使用哪个层次即可,不需要一股脑的全部使用。

BeanFactory顶级接口方法栈如下 :

 BeanFactory的容器继承体系:

通过BeanFactory的接口继承体系,可以看到经常使用的ApplicationContext除了继承了BeanFactory的子接口,还继承了MessageSource、ResourceLoader等接口,因此ApplicationContext提供的功能也就更加丰富全面了

 本文就以ClassPathXmlApplicationContext,来探究Spring IoC容器的初始化流程。

3、具体源码探究

Bean生命周期的关键时机点

通过创建几个Bean类,让其分别实现 BeanPostProcessor(Bean的后置处理器)、BeanFactoryPostProcessor(BeanFactory的后置处理器),通过断点观察调用栈来分析Bean对象创建和管理关键点的出发时机

UserBean类

public class UserBean implements InitializingBean{

	/**
	 * 构造函数
	 */
	public UserBean(){
		System.out.println("UserBean 构造器...");
	}


	/**
	 * InitializingBean 接口实现
	 */
	public void afterPropertiesSet() throws Exception {
		System.out.println("UserBean afterPropertiesSet...");
	}

}
BeanPostProcessor 接⼝实现类
public class MyBeanPostProcessor implements BeanPostProcessor {

	public MyBeanPostProcessor() {
		System.out.println("BeanPostProcessor 实现类构造函数...");
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if("userBean".equals(beanName)) {
			System.out.println("BeanPostProcessor 实现类 postProcessBeforeInitialization 方法被调用中......");
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if("userBean".equals(beanName)) {
			System.out.println("BeanPostProcessor 实现类 postProcessAfterInitialization 方法被调用中......");
		}
		return bean;
	}
}
BeanFactoryPostProcessor 接⼝实现类
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	public MyBeanFactoryPostProcessor() {
		System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("BeanFactoryPostProcessor的实现方法调用中......");
	}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans
 https://www.springframework.org/schema/beans/spring-beans.xsd
">

<bean id="userBean" class="com.demo.spring.UserBean"/>
<bean id="myBeanFactoryPostProcessor" class="com.demo.spring.MyBeanFactoryPostProcessor"/>
<bean id="myBeanPostProcessor" class="com.demo.spring.MyBeanPostProcessor"/>

</beans>

ClassPathXmlApplicationContext容器分析代码


	@Test
	public void testIoC() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		UserBean userBean= applicationContext.getBean(UserBean.class);
		System.out.println(userBean);
	}

(1)分析Bean的创建是在容器初始化的时候还是在getBean时

 通过断点调试,可以发现在没有设置延迟加载的情况下,Bean的创建是在容器初始化的时候完成的

(2)分析构造函数调用情况

 

 通过观察调用栈,可以发现构造函数的调用时机是在AbstractApplicationContext类refresh⽅法的 fifinishBeanFactoryInitialization(beanFactory)处;

 (3)分析 InitializingBean 的afterPropertiesSet初始化方法调用情况

观察调用栈


通过观察,可以发现InitializingBean中afterPropertiesSet方法的调用时机也是在AbstractApplicationContext类refresh⽅法的 fifinishBeanFactoryInitialization(beanFactory)处;

 (4)分析BeanFactoryPostProcessor 初始化和调⽤情况

分别在MyBeanFactoryPostProcessor的构造函数跟postProcessbeanFactory方法处打断点,观察调用栈,发现

BeanFactoryPostProcessor初始化在AbstractApplicationContext类refresh⽅法的invokeBeanFactoryPostProcessors(beanFactory);

postProcessBeanFactory 调⽤在AbstractApplicationContext类refresh⽅法的 invokeBeanFactoryPostProcessors(beanFactory);

(5)分析BeanPostProcessor初始化和调用情况

 

分别在MyBeanPostProcessor的构造函数、postProcessorBeforeInitialization和postProcessorAfterInitialization方法处打断点,观察调用栈,发现

BeanPostProcessor 初始化在AbstractApplicationContext类refresh⽅法的 registerBeanPostProcessors(beanFactory);

postProcessBeforeInitialization 调⽤在AbstractApplicationContext类refresh⽅法的 finishBeanFactoryInitialization(beanFactory);

postProcessAfterInitialization 调⽤在AbstractApplicationContext类refresh⽅法的 finishBeanFactoryInitialization(beanFactory);

(6)总结

根据上⾯的调试分析,我们发现 Bean对象创建的⼏个关键时机点代码层级的调⽤都在 AbstractApplicationContext 类 的 refresh ⽅法中,可⻅这个⽅法对于Spring IoC 容器初始化来说相当 关键,汇总如下:

关键点触发代码
构造器refresh#fifinishBeanFactoryInitialization(beanFactory)(beanFactory)
BeanFactoryPostProcessor 初始化refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanFactoryPostProcessor ⽅法调⽤refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanPostProcessor 初始化registerBeanPostProcessors(beanFactory)
BeanPostProcessor ⽅法调⽤refresh#fifinishBeanFactoryInitialization(beanFactory)

4、SpringIoC主流程

由上分析可知,Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() ⽅法中 ,我们查看 refresh ⽅法来俯瞰容器创建的主体流程,主体流程下的具体⼦流程我们后⾯再来讨论。

进入ClassPathXmlApplicationContext的构造方法

下图中的refresh()方法就是IOC容器初始化的关键方法了

点击构造方法中的refresh()方法进入 AbstractApplicationContext的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 第一步:刷新前的预处理
		prepareRefresh();

		/*
		 * 第二步:
		 * 获取beanFactory 默认实现是DefaultListableBeanFactory
		 * 加载BeanDefition 并注册到BeanDefitionRegistry
		 */
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		//第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等)
		prepareBeanFactory(beanFactory);

		try {
			// 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
			postProcessBeanFactory(beanFactory);

			// 第五步:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
			invokeBeanFactoryPostProcessors(beanFactory);

			//  第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执⾏
			registerBeanPostProcessors(beanFactory);

			// 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
			initMessageSource();

			// 第⼋步:初始化事件派发器
			initApplicationEventMulticaster();

			// 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
			onRefresh();

			// 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
			           registerListeners();
			/*
				 第⼗⼀步:
				 初始化所有剩下的⾮懒加载的单例bean
				 初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性)
				 填充属性
				 初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法)
				 调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处
			 */
			finishBeanFactoryInitialization(beanFactory);

			/*
				第⼗⼆步:完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅                
                         法,并且发布事件 (ContextRefreshedEvent)
			*/
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// 销毁已创建的单例bean
			destroyBeans();

			// 重置容器标志
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// 重置公共内省缓存
			resetCommonCaches();
		}
	}
}

以上代码就是整个SpringIOC容器初始化的主流程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值