Processus de chargement des conteneurs IOC Spring 6 et analyse du code source d'actualisation de la méthode principale

Préface : Cet article trie et analyse uniquement la logique de base de la ligne principale. Cet article prend le conteneur AnnotationConfigApplicationContext comme exemple à analyser [Version printemps : v6.0.2]

1. Instanciez le conteneur AnnotationConfigApplicationContext

Lorsque nous avons démarré le conteneur, bien que seul un nouvel objet AnnotationConfigApplicationContext ait été créé, Spring a géré beaucoup de choses dans le processus.

Créer un objet AnnotationConfigApplicationContext

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);

Le diagramme de structure de classe d'AnnotationConfigApplicationContext est le suivant :

insérez la description de l'image ici

Entrez le constructeur paramétré de la classe AnnotationConfigApplicationContext

	/**
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given component classes and automatically refreshing the context.
	 * @param componentClasses one or more component classes — for example,
	 * {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    
    
		// 调用无参构造函数
		this();
		// 注册配置类为BeadDefinition
		register(componentClasses);
		// IOC容器刷新
		refresh();
	}

1. this() méthode de construction sans paramètre

La structure sans argument instancie principalement le lecteur et le scanner . Le lecteur est le lecteur de définition de bean responsable du type d'annotation. Le type du scanner est ClassPathBeanDefinitionScanner. Il appelle simplement la méthode .scan manuellement à l'extérieur, ou Appelez le constructeur dont le paramètre est une chaîne et transmettez le nom du package à analyser avant qu'il ne soit utilisé.

	/**
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	// 调用本构造方法之前会先去调用父类GenericApplicationContext的构造函数
	public AnnotationConfigApplicationContext() {
    
    
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		// 创建一个读取注解的Bean定义的读取器,完成了spring内部BeanDefinition的注册
		this.reader = new AnnotatedBeanDefinitionReader(this);
		createAnnotatedBeanDefReader.end();
		// 创建BeanDefinition扫描器,可以用来扫描包或者类,继而转换成bean定义
		// 注意:spring默认的扫描包不是这个scanner对象,而是自己new的一个ClassPathBeanDefinitionScanner
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

2. Instanciez la fabrique de haricots : DefaultListableBeanFactory

Dans le code source ci-dessus, le constructeur de la classe parent est implicitement appelé, c'est-à-dire que le constructeur de GenericApplicationContext est appelé. Dans cette méthode de construction, une beanFactory (DefaultListableBeanFactory) est créée pour produire et obtenir Bean.

	/**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
    
    
		// 为ApplicationContext spring上下文对象初始化beanFactory,
		// DefaultListableBeanFactory在顶级接口BeanFactory基础上扩展了更多的功能,比如它实现了BeanDefinitionRegistry接口,拥有注册bean定义的能力
		this.beanFactory = new DefaultListableBeanFactory();
	}

Diagramme de structure de classe DefaultListableBeanFactory :

  • DefaultListableBeanFactory implémente l'interface BeanDefinationRegistry et a la capacité d'enregistrer les définitions de bean. L'enregistrement de la définition du bean plus tard est que cette classe est responsable de
    insérez la description de l'image ici

3. Instanciez le lecteur BeanDefinition : AnnotatedBeanDefinitionReader

	/**
	 * Create a new {@code AnnotatedBeanDefinitionReader} for the given registry,
	 * using the given {@link Environment}.
	 * @param registry the {@code BeanFactory} to load bean definitions into,
	 * in the form of a {@code BeanDefinitionRegistry}
	 * @param environment the {@code Environment} to use when evaluating bean definition
	 * profiles.
	 * @since 3.1
	 */
	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    
    
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		// 把ApplicationContext对象的registry,赋值给AnnotatedBeanDefinitionReader
		this.registry = registry;
		// 处理条件注解 @Condition
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		// 注册一些spring的内置后置处理器
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

4. Créez un scanner BeanDefinition : ClassPathBeanDefinitionScanner

Généralement, le scanner dans AnnotationConfigApplicationContext ne sera pas utilisé. Le scanner ici est uniquement destiné aux programmeurs pour appeler manuellement la méthode scan de l'objet AnnotationConfigApplicationContext.

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.scan();

5. Enregistrez la classe de configuration en tant que BeanDefinition : register(annotatedClasses)

Register est la méthode mentionnée au début. Analysons la méthode register(annotatedClasses). Sa fonction principale est d'enregistrer la classe de configuration en tant que définition de bean.
insérez la description de l'image ici

	/**
	 * Register one or more component classes to be processed.
	 * <p>Note that {@link #refresh()} must be called in order for the context
	 * to fully process the new classes.
	 * @param componentClasses one or more component classes &mdash; for example,
	 * {@link Configuration @Configuration} classes
	 * @see #scan(String...)
	 * @see #refresh()
	 */
	@Override
	public void register(Class<?>... componentClasses) {
    
    
		Assert.notEmpty(componentClasses, "At least one component class must be specified");
		StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
				.tag("classes", () -> Arrays.toString(componentClasses));
		// 注册
		this.reader.register(componentClasses);
		registerComponentClass.end();
	}

Continuez à descendre et entrez this.reader.register()la méthode

	/**
	 * Register one or more component classes to be processed.
	 * <p>Calls to {@code register} are idempotent; adding the same
	 * component class more than once has no additional effect.
	 * @param componentClasses one or more component classes,
	 * e.g. {@link Configuration @Configuration} classes
	 */
	public void register(Class<?>... componentClasses) {
    
    
		// 配置类可以传入多个,因此需要遍历注册
		for (Class<?> componentClass : componentClasses) {
    
    
			registerBean(componentClass);
		}
	}

Continuez dans registerBean()la méthode, puis dans doRegisterBean()la méthode :

	/**
	 * Register a bean from the given bean class, deriving its metadata from
	 * class-declared annotations.
	 * @param beanClass the class of the bean
	 * @param name an explicit name for the bean
	 * @param qualifiers specific qualifier annotations to consider, if any,
	 * in addition to qualifiers at the bean class level
	 * @param supplier a callback for creating an instance of the bean
	 * (may be {@code null})
	 * @param customizers one or more callbacks for customizing the factory's
	 * {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
	 * @since 5.0
	 */
	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
    
    
		// 把传入的标记了注解的类转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		// 判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就会跳过
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
    
    
			return;
		}

		abd.setInstanceSupplier(supplier);
		// 解析bean的作用域,如果没有配置,默认是单例
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		// processCommonDefinitionAnnotations方法是解析通用注解,填充到AnnotatedGenericBeanDefinition,
		// 解析的注解为Lazy,Primary,DependsOn,Role,Description
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		if (qualifiers != null) {
    
    
			for (Class<? extends Annotation> qualifier : qualifiers) {
    
    
				if (Primary.class == qualifier) {
    
    
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
    
    
					abd.setLazyInit(true);
				}
				else {
    
    
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		if (customizers != null) {
    
    
			for (BeanDefinitionCustomizer customizer : customizers) {
    
    
				customizer.customize(abd);
			}
		}

		// 存放BeanDefinition、bean的名字还有bean的别名信息
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		
		// 注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法注册
		// DefaultListableBeanFactory会维护一系列的信息,比如beanDefinitionNames、beanDefinitionMap
		// beanDefinitionNames是一个List<String>,用于保存beanName, 最终将配置类的bean定义注册到beanDefinitionMap中
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

6. La méthode de base refresh()

En fait, avant que la méthode d'actualisation ne soit appelée, Spring n'a pas encore analysé, mais instancié une usine, enregistré certains beans intégrés et la classe de configuration que nous avons transmise, et le processus le plus important est terminé dans la méthode d'actualisation.

Rafraîchir l'affichage du code source :

	public void refresh() throws BeansException, IllegalStateException {
    
    
		synchronized (this.startupShutdownMonitor) {
    
    
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
    
    
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

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

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
    
    
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

6.1、 prepareRefresh()

Cette méthode est utilisée pour préparer le conteneur avant l'actualisation, y compris la définition de l'état du contexte, l'obtention des propriétés, la vérification des propriétés nécessaires, etc. (Le code dans la partie centrale a une description en chinois)

	/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
    
    
		// Switch to active.
		// 设置启动时间
		this.startupDate = System.currentTimeMillis();  
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
    
    
			if (logger.isTraceEnabled()) {
    
    
				logger.trace("Refreshing " + this);
			}
			else {
    
    
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		// 交给子类实现,初始化属性源
		initPropertySources();  

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		// 验证所有标记为必须的属性
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
    
    
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
    
    
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

Les développeurs peuvent implémenter la méthode initPropertySources() pour ajouter des propriétés ou définir des propriétés qui doivent être vérifiées (lors de la vérification des propriétés, il sera vérifié s'il existe une configuration my-age), comme suit :

getEnvironment().setRequiredProperties("my-age");

6.2、obtenirFreshBeanFactory()

Cette méthode obtient un nouveau beanFactory. La méthode est très simple, actualisez BeanFactory et obtenez getBeanFactory.

	/**
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    
    
		// 刷新 BeanFactory
		refreshBeanFactory();
		// 获取 getBeanFactory
		return getBeanFactory();
	}

6.3、prepareBeanFactory(beanFactory)

Cette méthode est utilisée pour configurer beanFactory standard, définir ClassLoader, définir l'analyseur d'expression SpEL, ajouter une interface qui ignore l'injection, ajouter un bean, ajouter un post-processeur de bean, etc.

	/**
	 * Configure the factory's standard context characteristics,
	 * such as the context's ClassLoader and post-processors.
	 * @param beanFactory the BeanFactory to configure
	 */
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    
    
		// Tell the internal bean factory to use the context's class loader etc.
		// 设置 beanFactory 的类加载器
		beanFactory.setBeanClassLoader(getClassLoader());
		// 设置支持表达式解析器
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		// 为 beanFactory 增加了一个默认的 propertyEditor ,这个主要是对 bean 的属性等设置管理的一个工具
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		// 添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		// 设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		// 注册可以解析的自动装配
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    
    
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		// 注册环境属性
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    
    
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		// 注册系统属性
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
    
    
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		// 注册系统环境变量
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
    
    
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		// 注册应用程序启动bean名称
		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
    
    
			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
		}
	}

6.4、postProcessBeanFactory(beanFactory)

À ce stade, toutes les beanDefinitions ont été chargées, mais pas encore instanciées pour permettre un traitement étendu de beanFactory dans les sous-classes. Par exemple, l'ajout de paramètres d'assemblage automatique d'interface liés aux articles, l'ajout de post-processeurs, etc., est une méthode permettant aux sous-classes d'étendre prepareBeanFactory(beanFactory).

6.5、invokeBeanFactoryPostProcessors(beanFactory)

Instancie et appelle tous les post-processeurs beanFactory enregistrés (beans qui implémentent l'interface BeanFactoryPostProcessor, exécutés après l'initialisation standard de beanFactory).

	/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before singleton instantiation.
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    
    
		// 执行BeanFactoryPostProcessor的方法
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    
    
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}
  • Dans la méthode beginBeanFactoryPostProcessors, Spring recherche d'abord tous les post-processeurs BeanFactory qui implémentent BeanDefinitionRegistryPostProcessor, puis implémente d'abord PriorityOrdered, puis Ordered.

  • Le plus célèbre d'entre eux est ConfigurationClassPostProcessor, qui est utilisé pour analyser les objets marqués par @Component et @Bean, et enregistrer leurs métadonnées BeanDefinition dans le BeanDefinitionMap du conteneur Spring. Allez ensuite chercher tous les post-processeurs BeanFactory, supprimez ceux qui ont déjà été exécutés, et exécutez-les dans l'ordre selon le tri. Une fois cette méthode terminée, le post-processeur BeanFactory a été enregistré et exécuté dans le contexte Spring, et une partie de la BeanDefinition a également été enregistrée.

6.6. Enregistrer les post-processeurs Bean : registerBeanPostProcessors(beanFactory)

Enregistrez les post-processeurs Bean, obtenez les noms de tous les post-processeurs Bean et classez les post-processeurs Bean. Une fois la classification effectuée, tous les PriorityOrderedPostProcessors deviendront un Bean et entreront dans le conteneur Spring. Étant donné que le code source est assez désordonné, seules les parties clés du code sont triées ici :

		// 1.获取所有的 Bean 后置处理器的名字
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
		
		// 2.对 Bean 后置处理器分类
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		
		...

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		// 3.注册 Bean 后置处理器
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
		// Finally, re-register all internal BeanPostProcessors.
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

6.7. Traitement de l'internationalisation : initMessageSource()

Initialise la source de message pour le contexte et internationalise les corps de message dans différentes langues.

6.8. Initialiser le diffuseur d'événements : initApplicationEventMulticaster()

	/**
	 * Initialize the ApplicationEventMulticaster.
	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	protected void initApplicationEventMulticaster() {
    
    
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
    
    
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isTraceEnabled()) {
    
    
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
    
    
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isTraceEnabled()) {
    
    
				logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
						"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
			}
		}
	}

6.9. Enregistrez l'écouteur : registerListeners()

	/**
	 * Add beans that implement ApplicationListener as listeners.
	 * Doesn't affect other listeners, which can be added without being beans.
	 */
	protected void registerListeners() {
    
    
	
		// 1. 添加指定的监听器
		for (ApplicationListener<?> listener : getApplicationListeners()) {
    
    
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

		// 2. 获取所有实现 ApplicationListener 的广播器,并添加
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
    
    
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// Publish early application events now that we finally have a multicaster...
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
    
    
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    
    
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

6.10、finishBeanFactoryInitialization(beanFactory)

L'instanciation de tous les singletons chargés non paresseux restants, tels que les classes analysées selon diverses annotations dans la méthode invokeBeanFactoryPostProcessors, sera initialisée à ce moment. Le processus d'instanciation des différents BeanPostProcessor commence à fonctionner.

		// 1. 冻结所有的 bean,已经注册的 bean 定义将不会被修改或任何进一步的处理
		beanFactory.freezeConfiguration();

		// 2. 实例化所有剩余的非懒加载的 bean
		beanFactory.preInstantiateSingletons();
// 获取容器中所有 beanDefinition 的名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

for (String beanName : beanNames) {
    
    
	// 根据 beanName 获取 BeanDefinition
	RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
	// 不是抽象的 && 是单例的 && 不是懒加载的
	if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    
    
		if (isFactoryBean(beanName)) {
    
    
			// 如果是 FactoryBean,就先获取 FactoryBean 实例
			Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
			if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
    
    
				getBean(beanName);
			}
		}
		else {
    
    
			// 如果不是 FactoryBean,就直接获取 Bean
			getBean(beanName);
		}
	}
}

6.11、finishRefresh()

Effacez le cache des ressources de contexte (comme les métadonnées ASM dans l'analyse), initialisez le processeur de cycle de vie du contexte, actualisez-le et publiez l'événement ContextRefreshedEvent pour informer l'ApplicationListener correspondant de répondre

	protected void finishRefresh() {
    
    
		// Clear context-level resource caches (such as ASM metadata from scanning).
		// 清除上下文资源缓存(如扫描中的ASM元数据) scanning).
		clearResourceCaches();

		// Initialize lifecycle processor for this context.
		// 初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		// 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作
		publishEvent(new ContextRefreshedEvent(this));
	}

Ce qui précède est le processus de chargement du conteneur Spring 6 IOC et le processus d'analyse du code source d'actualisation de la méthode principale, j'espère que cela vous sera utile.

Je suppose que tu aimes

Origine blog.csdn.net/qq_40436854/article/details/129889039
conseillé
Classement