The Spring IoC container initialization process is fully analyzed and implemented with code!

1. The container system of Spring IoC

The IoC container is the core module of Spring and a framework solution that abstracts object management and dependency management . Spring provides a container, which BeanFactoryis the top container (Root container) , can not be instantiated, which defines a set of principles must comply with all IoC container, particularly a container may implement additional features, such as we used to ApplicationContext, more specifically, under such implementation ClassPathXmlApplicationContextincludes a set of xml content analysis and the like, AnnotationConfigApplicationContextthe content comprising a series of notes analysis or the like. The Spring IoC container inheritance system is very smart. You can use which level you need to use, instead of using large and complete functions.

BeanFactoryTop-level interface method stacks as follows

BeanFactoryvessel inheritance system

Connector through its design, we can see that we have always used ApplicationContextin addition to inheriting BeanFactorysub-interface, also inherited ResourceLoader, MessageSourceand other interfaces, so its function also provides richer.

Here we have ClasspathXmlApplicationContext, for example, in-depth explanation of source IoC container initialization process.


This article references "Spring Advanced Source Notes", students who need to add assistant VX: C18173184271 free access

Second, the key timing of the Bean life cycle

Idea: Create a class LagouBean, let it implement several special interfaces, and observe the thread call stack in the constructor and interface method interruption points of the interface implementation, and analyze the trigger timing of the key points of Bean object creation and management.

LagouBeanclass

package com.lagou;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
* @Author 应癫
* @create 2019/12/3 11:46
*/
public class LagouBean implements InitializingBean{
    
    
 
 /**
 * 构造函数
 */
	public LagouBean(){
    
    
		System.out.println("LagouBean 构造器...");
	}
 /**
 * InitializingBean 接⼝实现
 */
	public void afterPropertiesSet() throws Exception {
    
    
		System.out.println("LagouBean afterPropertiesSet...");
	} 
}

BeanPostProcessor Interface implementation class

package com.lagou;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
* @Author 应癫
* @create 2019/12/3 16:59
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
    
    
 
public MyBeanPostProcessor() {
    
    
 	System.out.println("BeanPostProcessor 实现类构造函数...");
}

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

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

BeanFactoryPostProcessor Interface implementation class

package com.lagou;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
* @Author 应癫
* @create 2019/12/3 16:56
*/

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="lagouBean" class="com.lagou.LagouBean"/>
 <bean id="myBeanFactoryPostProcessor"
class="com.lagou.MyBeanFactoryPostProcessor"/>
 <bean id="myBeanPostProcessor" class="com.lagou.MyBeanPostProcessor"/>
</beans>

IoC container source code analysis use case

/**
* Ioc 容器源码分析基础案例
*/
@Test
public void testIoC() {
    
    
	ApplicationContext applicationContext = new 
ClassPathXmlApplicationContext("classpath:applicationContext.xml");
	LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
	System.out.println(lagouBean);
}

1. Analyze whether the creation of the Bean is at the time of container initialization or at the time of getBean


According to the breakpoint debugging, we found that the creation of the Bean is completed during the initialization of the container without setting delayed loading.

2. Analyze the constructor call



Through the above observation, we found that the call timing of the constructor is in the refresh method of the AbstractApplicationContext class ;finishBeanFactoryInitialization(beanFactory)

3. Analyze the invocation of the afterPropertiesSet initialization method of InitializingBean


Observe the call stack

above observation, we found that InitializingBeanin afterPropertiesSet method call timing is in AbstractApplicationContext class refresh method of finishBeanFactoryInitialization(beanFactory);

4. Analyze the initialization and invocation of BeanFactoryPostProcessor

Break points at the constructor and postProcessBeanFactorymethod respectively , observe the call stack, and find

BeanFactoryPostProcessor is initialized in the refresh method of the AbstractApplicationContextclass ;invokeBeanFactoryPostProcessors(beanFactory)

postProcessBeanFactory call AbstractApplicationContextclass refresh method of invokeBeanFactoryPostProcessors(beanFactory);

5. Analyze the initialization and invocation of BeanPostProcessor

Break points at the constructor and postProcessBeanFactorymethod respectively , observe the call stack, and find

BeanPostProcessor is initialized in the refresh method of the AbstractApplicationContextclass ;registerBeanPostProcessors(beanFactory)

postProcessBeforeInitialization call AbstractApplicationContextclass refresh method of finishBeanFactoryInitialization(beanFactory);

postProcessAfterInitialization call AbstractApplicationContextclass refresh method of finishBeanFactoryInitialization(beanFactory);

6. Summary

According to the above debugging analysis, we found that several key timing points of Bean object creation are called in
AbstractApplicationContextthe refresh method of the class . It can be seen that this method is quite critical for the initialization of the Spring IoC container . The summary is as follows:

Three, Spring IoC container initialization main process

From the above analysis shows, the Spring IoC container initialization key link in the AbstractApplicationContext#refresh()process, we see the refresh method to overlook the main flow of container to create the specific sub-processes of the body processes come under discussion behind us.

@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();
		}
		......
 	}
}

If you need this full version of "Spring Advanced Source Notes", you only need to support my article.

A lot of support, you can get information for free-after three consecutive years (promise: 100% free)

Quick start channel: Add assistant VX: C18173184271 Get it for free! Full of sincerity! ! !

Guess you like

Origin blog.csdn.net/Java_Caiyo/article/details/112910150