09、SpringBoot 启动 刷新应用上下文 自动装配解析(一)

目录Springboot源码学习目录
上文08、SpringBoot 启动 准备应用上下文
前言

一、属性应用上下文

debug进入refreshContext方法

	private void refreshContext(ConfigurableApplicationContext context) {
		if (this.registerShutdownHook) {
			try {
				context.registerShutdownHook();
			}
			catch (AccessControlException ex) {
				// Not allowed in some environments.
			}
		}
                // 进入刷新方法
		refresh((ApplicationContext) context);
	}
	protected void refresh(ApplicationContext applicationContext) {
		Assert.isInstanceOf(ConfigurableApplicationContext.class, applicationContext);
                // 进入重载刷新方法
		refresh((ConfigurableApplicationContext) applicationContext);
	}
	protected void refresh(ConfigurableApplicationContext applicationContext) {
                // 调用上下文自己的刷新方法
		applicationContext.refresh();
	}

调用到上下文自己的刷新方法,我们就发现就是之前的spring的逻辑
原有的spring逻辑我们就不再看了,这里只看一下springboot特有并且比较重要的的逻辑

        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.
                                // beanFactory后处理,向工厂中注入WebApplicationContextServletContextAwareProcessor,这一步我们不用太关心
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
                                // 回调所有的 BeanFactoryPostProcessor,其中自动装配就是在该步完成,重点要关心的
				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.
                                // 创建并启动 Tomcat 服务器,就是在该步完成,重点要关心的
				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();
			}
		}
	}

二、回调所有的 BeanFactoryPostProcessor

debug进入invokeBeanFactoryPostProcessors方法

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

PostProcessorRegistrationDelegateinvokeBeanFactoryPostProcessors方法逻辑很复杂,这个和Spring一样,这里我们只看和自动装配有关的那个 BeanFactoryPostProcessor

	public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
                // 省略不重要逻辑---

		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
                // 在呈现的部分代码里上面那部分代码就是获取所有BeanDefinitionRegistryPostProcessor的实现类,然后调用
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
		currentRegistryProcessors.clear();

                // 省略不重要逻辑---        
        }

然后遍历所有的BeanDefinitionRegistryPostProcessor的实现类
我们在前文创建 应用上下文时说过,在创建过程中想上下文beanFactory中注册了一个ConfigurationClassPostProcessor,这个类也实现了BeanDefinitionRegistryPostProcessor
ConfigurationClassPostProcessor也是我们重点关注的类,自动装配就和他有关系,我们只需要debug他就可以了

	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
					.tag("postProcessor", postProcessor::toString);
                        // 找到ConfigurationClassPostProcessor然后执行
			postProcessor.postProcessBeanDefinitionRegistry(registry);
			postProcessBeanDefRegistry.end();
		}
	}

进入ConfigurationClassPostProcessor

	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
                // 省略不重要代码 ......
                // ConfigurationClassPostProcessor解析的核心方法
		processConfigBeanDefinitions(registry);
	}

然后我们进入ConfigurationClassPostProcessorprocessConfigBeanDefinitions方法,

	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
                // 获取当前beanFactory中的所有beanName
		String[] candidateNames = registry.getBeanDefinitionNames();
                
                // 遍历当前beanFactory中的所有beanName,因为还出去回调beanFactroyPostProcessor阶段,工厂中的beanName只有几个
		for (String beanName : candidateNames) {
                        // 获取beanName对应的BeanDefinition
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
                        // CONFIGURATION_CLASS_ATTRIBUTE = "org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass"
                        // 如果BeanDefinition 中有 CONFIGURATION_CLASS_ATTRIBUTE属性,说明这个bean已经被解析过了,不需要再解析
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
                        //  如果BeanDefinition 中没有 CONFIGURATION_CLASS_ATTRIBUTE属性,则需要判断是否需要解析
                        // 判断逻辑就不看了,在这里直接写,当类上面标注了@Configuration/@Component/@ComponentScan/@Import/@ImportResource等注解,就是配置类,需要进行后面的解析
                        // 这个工具类的方法后面还会用到
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
                // 判断是否为空,如果为空则说明没有需要解析的配置类,直接返回,一般第一次启动,我们能拿到的配置类就是我们的启动类,
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
                // 对需要解析的配置类进行排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// Detect any custom bean name generation strategy supplied through the enclosing application context
		SingletonBeanRegistry sbr = null;
                
                // registry实现了SingletonBeanRegistry,此处为true
		if (registry instanceof SingletonBeanRegistry) { 
                        // 将registry强转为SingletonBeanRegistry
			sbr = (SingletonBeanRegistry) registry;
                        
                        // 默认为false,此处也成立
			if (!this.localBeanNameGeneratorSet) {
                                // 从工厂中获取org.springframework.context.annotation.internalConfigurationBeanNameGenerator,对应的bean
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
                                // 第一次创建应用上下文,为空,
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

                // 实例化时将上下文中的环境赋值给了当前对象,此处不为空
		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

                
		// Parse each @Configuration class
                // 配置类解析器,不要被此处的英文误导了,这个解析器可以解析@Component,@PropertySources,@ComponentScans,@Import,@ImportResource,@Bean这些注解
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

                // 将待解析的BeanDefinitionHolder存入candidates集合,后面遍历解析
		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
                // 收集已经解析过的类
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
                // 循环解析
		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
                        // 开始解析 上面存入candidates集合的配置类,核心逻辑
			parser.parse(candidates);
                        // 遍历所有解析出来的类,检查标注有@Configuration注解且proxyBeanMethods属性=true的类与其@bean标注的方法是不是fianl关键字修饰,如果是则报错
			parser.validate();

                        // 获取所有的解析出来的配置类,存入configClasses集合
			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
                        //删除掉配置类集合中已经解析过的配置类,防止重复解析
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content

                        // 如果读取器为空,则创建一个,配置类bean定义信息读取器,该读取器专门将配置类解析成BeanDefinition
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
                        // 将配置类解析为beanDefinition,核心逻辑
			this.reader.loadBeanDefinitions(configClasses);
                        
                        // 将解析过的配置类加入已解析集合
			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

                        // 清空待解析的配置类
			candidates.clear();
                        // 如果解析后的 BeanDefinition 的总数 > 大于解析前的  BeanDefinition 的总数,则需要检查新增的bean中是否有配置类
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
                                // 获取所有的beanName
				String[] newCandidateNames = registry.getBeanDefinitionNames();
                                // 获取所有解析之前的beanName
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                                // 收集所有已解析的beanName
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
                                // 遍历所有的beanName,如果他在解析之前不存在,则获取他的他BeanDefinition
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
                                                // 然后检查,这个类是不是配置类,并且没有解析过,如果是,则加入待解析的配置类中
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
                                /// 同时将解析前所有配置类更新
				candidateNames = newCandidateNames;
			}
		}
		while (!candidates.isEmpty());

		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			// Clear cache in externally provided MetadataReaderFactory; this is a no-op
			// for a shared cache since it'll be cleared by the ApplicationContext.
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

上面这段解析流程中,最重要的是parser.parse(candidates);this.reader.loadBeanDefinitions(configClasses);这两行代码
parser.parse(candidates);代表的是将待解析的配置类中的类解析出来,而自动装配的逻辑也在其中
this.reader.loadBeanDefinitions(configClasses);代表的时候将解析出来的类,转化为 BeanDefinition
我们下篇文章再分析

posted @ 2021-11-14 08:12  君子思  阅读(466)  评论(0)    收藏  举报