Le processus d'initialisation du conteneur Spring IoC est entièrement analysé et implémenté avec du code!

1. Le système de conteneurs de Spring IoC

Le conteneur IoC est le module principal de Spring et une solution de cadre qui résume la gestion des objets et la gestion des dépendances . Spring fournit un conteneur, qui BeanFactoryest le conteneur supérieur (conteneur racine) , ne peut pas être instancié, qui définit un ensemble de principes doit être conforme à tous les conteneurs IoC, en particulier un conteneur peut implémenter des fonctionnalités supplémentaires, comme nous le faisions auparavant ApplicationContext, plus spécifiquement, dans le cadre d'une telle mise en œuvre ClassPathXmlApplicationContextcomprend un ensemble d'analyse de contenu xml et analogues, AnnotationConfigApplicationContextle contenu comprenant une série d'analyse de notes ou similaire. Le système d'héritage de conteneurs Spring IoC est très intelligent. Vous pouvez utiliser le niveau que vous devez utiliser, au lieu d'utiliser des fonctions volumineuses et complètes.

BeanFactoryMéthode d'interface de niveau supérieur empile comme suit

BeanFactorysystème d'héritage de navire

Connecteur grâce à sa conception, nous pouvons voir que nous avons toujours utilisé ApplicationContexten plus d'hériter de BeanFactorysous-interface, également héritée ResourceLoader, MessageSourceet d'autres interfaces, de sorte que sa fonction fournit également plus riche.

Ici, nous avons ClasspathXmlApplicationContext, par exemple, une explication approfondie du processus d'initialisation du conteneur IoC source.


Cet article fait référence à "Spring Advanced Source Notes", les étudiants qui doivent ajouter l'assistant VX: C18173184271 accès gratuit

Deuxièmement, le moment clé du cycle de vie du haricot

Idée: Créez une classe LagouBean, laissez-la implémenter plusieurs interfaces spéciales et observez la pile d'appels de thread dans les points d'interruption du constructeur et de la méthode d'interface de l'implémentation de l'interface, et analysez le timing de déclenchement des points clés de la création et de la gestion des objets Bean.

LagouBeanclasse

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 Classe d'implémentation d'interface

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 Classe d'implémentation d'interface

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>

Cas d'utilisation de l'analyse du code source du conteneur IoC

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

1. Analysez si la création du Bean est au moment de l'initialisation du conteneur ou au moment de getBean


D'après le débogage des points d'arrêt, nous avons constaté que la création du Bean est terminée lors de l'initialisation du conteneur sans paramétrer le chargement différé.

2. Analysez l'appel du constructeur



Grâce à l'observation ci-dessus, nous avons constaté que la synchronisation de l'appel du constructeur est dans la méthode de rafraîchissement de la classe AbstractApplicationContext ;finishBeanFactoryInitialization(beanFactory)

3. Analysez l'appel de la méthode d'initialisation afterPropertiesSet d'InitializingBean


Observez la pile d'appels

ci-dessus, nous avons constaté que InitializingBeandans la méthode afterPropertiesSet, la synchronisation des appels est dans la méthode de rafraîchissement de la classe AbstractApplicationContext de ;finishBeanFactoryInitialization(beanFactory)

4. Analysez l'initialisation et l'appel de BeanFactoryPostProcessor

Points de rupture au niveau du constructeur et de la postProcessBeanFactoryméthode respectivement , observez la pile d'appels et trouvez

BeanFactoryPostProcessor est initialisé dans la méthode de rafraîchissement de la AbstractApplicationContextclasse ;invokeBeanFactoryPostProcessors(beanFactory)

postProcessBeanFactory appelle la méthode d'actualisation de laAbstractApplicationContext classe de ;invokeBeanFactoryPostProcessors(beanFactory)

5. Analysez l'initialisation et l'appel de BeanPostProcessor

Points de rupture au niveau du constructeur et de la postProcessBeanFactoryméthode respectivement , observez la pile d'appels et trouvez

BeanPostProcessor est initialisé dans la méthode de rafraîchissement de la AbstractApplicationContextclasse ;registerBeanPostProcessors(beanFactory)

postProcessBeforeInitialization appelle la méthode d'actualisation de laAbstractApplicationContext classe de ;finishBeanFactoryInitialization(beanFactory)

postProcessAfterInitialization appelle la méthode d'actualisation de laAbstractApplicationContext classe de ;finishBeanFactoryInitialization(beanFactory)

6. Résumé

Selon l'analyse de débogage ci-dessus, nous avons constaté que plusieurs points de synchronisation clés de la création d'objet Bean sont appelés dans
AbstractApplicationContextla méthode d'actualisation de la classe . On peut voir que cette méthode est assez critique pour l' initialisation du conteneur Spring IoC . Le résumé est le suivant:

Trois, processus principal d'initialisation du conteneur Spring IoC

D'après l'analyse ci-dessus, le lien clé d' initialisation du conteneur Spring IoC dans le AbstractApplicationContext#refresh()processus, nous voyons la méthode d'actualisation pour ignorer le flux principal du conteneur pour créer les sous-processus spécifiques des processus corporels qui font l'objet de discussions derrière nous.

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

Si vous avez besoin de cette version complète de "Spring Advanced Source Notes", il vous suffit de soutenir mon article.

Beaucoup de soutien, vous pouvez obtenir des informations gratuitement après trois années consécutives (promesse: 100% gratuit)

Canal de démarrage rapide: Ajouter un assistant VX: C18173184271 Obtenez-le gratuitement! Plein de sincérité! ! !

Je suppose que tu aimes

Origine blog.csdn.net/Java_Caiyo/article/details/112910150
conseillé
Classement