SpringBoot 源码分析刷新应用上下文(3)-refreshContext

news2024/12/23 23:29:59

一:入口

/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 */
	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //主要看这个方法
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}
 
		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

refreshContext(context);

这一步会解析 @Import 注解,@ComponentScan 注解,通过扫描路径得到被 @Controller、@Service、@Component所标注的这些类并且实例对象存到 IOC 容器中。

二、refreshContext 方法实现

截图:

接着看 refresh(context);

截图:

代码:

 /**
     * Refresh the underlying {@link ApplicationContext}.
     * @param applicationContext the application context to refresh
     */
    protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
        //对 context 做了一个类型转换,然后继续调用 refresh() 方法
        ((AbstractApplicationContext) applicationContext).refresh();
        //转化成了 AbstractApplicationContext,是不是感到很熟悉,再进行 Spring 源码分析的时候就是主要分析的 AbstractApplicationContext 的 refresh() 方法,
        //其实现在我们已经走到了 spring 的源码中了,其实在上一步 prepareContext 中,已经完成了 springBoot 的创建,在进行 refreshContext() 方法执行的时候,剩下的创建对象的过程等等都是交给了 spring 来处理
    }

 接着看 refresh() 方法实现

截图:

代码:

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
            // 准备刷新此上下文
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
            // 告诉子类刷新内部bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
            // 准备bean工厂以便在此上下文中使用。
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
                // 允许在上下文子类中对bean工厂进行后处理
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
                // 调用在上下文中注册为bean的工厂处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
                // 注册拦截bean创建的bean处理器
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
                // 初始化此上下文的消息源
				initMessageSource();

				// Initialize event multicaster for this context.
                // 初始化此上下文的事件多播
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
                // 初始化特定上下文子类中的其他特殊bean
				onRefresh();

				// Check for listener beans and register them.
                // 检查侦听器bean并注册它们
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
                // 实例化所有剩余的(非惰性init)singleton
				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.
                // 销毁已创建的singleton以避免挂起资源
				destroyBeans();

				// Reset 'active' flag.
                // 重置“活动”标志
				cancelRefresh(ex);

				// Propagate exception to caller.
                // 向调用方传播异常
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
                // 重置Spring核心中的常见内省缓存,因为我们
				// might not ever need metadata for singleton beans anymore...
                // 可能不再需要单例bean的元数据了。。。
				resetCommonCaches();
			}
		}
	}

 接着看上面截图红框的方法  invokeBeanFactoryPostProcessors(beanFactory);

// Invoke factory processors registered as beans in the context.
 // 调用在上下文中注册为bean的工厂处理器
invokeBeanFactoryPostProcessors(beanFactory);

截图:

代码:

/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
     * 实例化并调用所有注册的BeanFactoryPostProcessor bean
	 * respecting explicit order if given.
     * 如果给定,则遵循显式顺序
	 * <p>Must be called before singleton instantiation.
     *    必须在单例实例化之前调用
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		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)
        //(例如,通过ConfigurationClassPostProcessor注册的@Bean方法)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

接着看 invokeBeanFactoryPostProcessors() 方法调用

截图:

代码:

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
        // 无论任何情况,最先执行 invokeBeanFactoryPostProcessors 方法
		Set<String> processedBeans = new HashSet<>();
            
        // 这里可以看下继承关系,判断下类型
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
            // 这里不要初始化FactoryBeans:我们需要保留所有常规bean
			// uninitialized to let the bean factory post-processors apply to them!
            // 未初始化以允许bean工厂后置处理器应用于它们!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
            // 在实现的BeanDefinitionRegistryPostProcessors之间分离
			// PriorityOrdered, Ordered, and the rest.
            // 优先级有序、有序和其他
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 首先,调用实现 PriorityOrdered 的 BeanDefinitionRegistryPostProcessors
			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);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            // 接下来,调用实现Ordered的BeanDefinitionRegistryPostProcessors
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            // 最后,调用所有其他 BeanDefinitionRegistryPostProcessors,直到不再出现其他处理器为止
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            // 现在,调用迄今为止处理的所有处理器的postProcessBeanFactory回调
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
            // 调用在上下文实例中注册的工厂处理程序
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
        // 这里不要初始化FactoryBeans:我们需要保留所有常规bean
		// uninitialized to let the bean factory post-processors apply to them!
        // 未初始化以允许bean工厂后处理器应用于它们!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // 在实现PriorityOrdered的BeanFactoryPostProcessors之间分离,
		// Ordered, and the rest.
        // 秩序井然,其余
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
                // 跳过-已在上面的第一阶段中处理
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        // 首先,调用实现PriorityOrdered的BeanFactoryPostProcessors
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        // 接下来,调用实现Ordered的BeanFactoryPostProcessors
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
        // 最后,调用所有其他BeanFactoryPostProcessors
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
        // 清除缓存的合并bean定义,因为后处理器可能具有
		// modified the original metadata, e.g. replacing placeholders in values...
        // 修改了原始元数据,例如替换值中的占位符。。。
		beanFactory.clearMetadataCache();
	}

 接着看上面红框的方法

截图:

这是一个接口,接着看其实现类,找到 ConfigurationClassPostProcessor 实现类

截图:

截图:

接着看 processConfigBeanDefinitions() 方法实现

截图:

代码:

/**
	 * Build and validate a configuration model based on the registry of
     * 基于的注册表构建和验证配置模型
	 * {@link Configuration} classes.
	 */
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();

		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
        // 如果未找到@Configuration类,则立即返回
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
        // 按先前确定的@Order值排序(如果适用)
		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
        // 检测通过封闭应用程序上下文提供的任何自定义bean名称生成策略
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				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
        // 分析每个@Configuration类
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
            // 阅读模型并根据其内容创建bean定义
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				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
        // 将 ImportRegistry 注册为 bean 以支持 ImportAware @Configuration 类
		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
            // 清除外部提供的 MetadataReaderFactory 中的缓存;这是禁止手术
			// for a shared cache since it'll be cleared by the ApplicationContext.
            // 用于共享缓存,因为它将被 ApplicationContext 清除
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

 2.1 接着看 parser.parse(candidates);

截图:

代码:

 //下面就是进入 ConfigurationClassParser.parse() 方法,这个方法很重要,首先获取启动累的 BeanDefinition,然后判断启动类是否是注解类,然后进行解析,然后下面就是真正来解析 @ComponentScan 和 @Import等注解的
   public void parse(Set<BeanDefinitionHolder> configCandidates) {
        for (BeanDefinitionHolder holder : configCandidates) {
            // 获取启动类的 BeanDefinition
            BeanDefinition bd = holder.getBeanDefinition(); 
            try {
                // 判断启动类是否是一个标注了注解的 bean
                if (bd instanceof AnnotatedBeanDefinition) { 
                    // 这里才是真正解析启动类里面的 @ComponentScan 和 @Import 的方法
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); 
                }
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }
        // 这里就是如何和开始讲的 DeferredImportSelectors.getImport() 方法如何串联起来
        // 延迟导入选择器处理程序
        this.deferredImportSelectorHandler.process(); 
    }

 接着看 parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());

截图:

接着看 processConfigurationClass(new ConfigurationClass(metadata, beanName));

截图:

代码:

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}

		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					existingClass.mergeImportedBy(configClass);
				}
				// Otherwise ignore new imported config class; existing non-imported class overrides it.
                // 否则,忽略新导入的配置类;现有的非导入类将覆盖它。
				return;
			}
			else {
				// Explicit bean definition found, probably replacing an import.
                // 找到显式bean定义,可能正在替换导入
				// Let's remove the old one and go with the new one.
                // 让我们去掉旧的,换上新的
				this.configurationClasses.remove(configClass);
				this.knownSuperclasses.values().removeIf(configClass::equals);
			}
		}

		// Recursively process the configuration class and its superclass hierarchy.
        // 递归处理配置类及其超类层次结构
		SourceClass sourceClass = asSourceClass(configClass);
		do {
            //以 do 开头,真正做事的方法,这就是为什么 @ComponentScan 能够获取到对应的扫描路径,从而把标注了 @Controller、@Service 等标注的对象生成实例对象存到 IOC 容器中
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}

接着看红框方法:sourceClass = doProcessConfigurationClass(configClass, sourceClass);

截图:

 代码:

/**
	 * Apply processing and build a complete {@link ConfigurationClass} by reading the
	 * annotations, members and methods from the source class. This method can be called
	 * multiple times as relevant sources are discovered.
     * 通过从源类中读取注释、成员和方法,应用处理并构建一个完整的 ConfigurationClass。
     * 当发现相关来源时,可以多次调用此方法
	 * @param configClass the configuration class being build --正在生成的配置类
	 * @param sourceClass a source class - 源类
	 * @return the superclass, or {@code null} if none found or previously processed
     * 返回超类,如果没有没有找到或者以前处理过,则为 null
	 */
	@Nullable
	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// Recursively process any member (nested) classes first
            // 首先递归处理所有成员(嵌套)类
			processMemberClasses(configClass, sourceClass);
		}

		// Process any @PropertySource annotations
        // 处理标注了 @PropertySource 的注释
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

		// Process any @ComponentScan annotations
        // 处理所有标注 @ComponentScan 的注释
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
                // 配置类注释为 @ComponentScan -> 立即执行扫描
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
                // 检查扫描的定义集是否有任何进一步的配置类,并在需要时递归解析
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// Process any @Import annotations
        // 处理所有标注了 @Import 的注释
		processImports(configClass, sourceClass, getImports(sourceClass), true);

		// Process any @ImportResource annotations
        // 处理所有标注了 @ImportResource 的注释
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

		// Process individual @Bean methods
        // 处理单个@Bean方法
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
        // 处理接口上的默认方法
		processInterfaces(configClass, sourceClass);

		// Process superclass, if any
        // 进程超类(如果有)
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}

 接着看红框的方法

Set<BeanDefinitionHolder> scannedBeanDefinitions =
      this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

截图:

代码:

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
				componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

		Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
		boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
		scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
				BeanUtils.instantiateClass(generatorClass));

		ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
		if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
			scanner.setScopedProxyMode(scopedProxyMode);
		}
		else {
			Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
			scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
		}

		scanner.setResourcePattern(componentScan.getString("resourcePattern"));

		for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addIncludeFilter(typeFilter);
			}
		}
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addExcludeFilter(typeFilter);
			}
		}

		boolean lazyInit = componentScan.getBoolean("lazyInit");
		if (lazyInit) {
			scanner.getBeanDefinitionDefaults().setLazyInit(true);
		}

		Set<String> basePackages = new LinkedHashSet<>();
        // 获取注解 @ComponentScan 的属性
		String[] basePackagesArray = componentScan.getStringArray("basePackages");
		for (String pkg : basePackagesArray) {
			String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
			Collections.addAll(basePackages, tokenized);
		}
		for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
			basePackages.add(ClassUtils.getPackageName(clazz));
		}
        // 如果 basePackages 为空
		if (basePackages.isEmpty()) {
            // 核心启动类,然后现在ComponentScan就可以扫描到包和子包路径下面的各种被标注的类,例如@Controller、@Service、@Component
            //那么这些对象又是怎么生成实例存到ioc容器当中的呢?调用scanner.doScan()方法
			basePackages.add(ClassUtils.getPackageName(declaringClass));
		}

		scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
			@Override
			protected boolean matchClassName(String className) {
				return declaringClass.equals(className);
			}
		});
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}

接着看 scanner.doScan(StringUtils.toStringArray(basePackages))

截图:

代码:

/**
	 * Perform a scan within the specified base packages, -- 在指定的基本包中执行扫描
	 * returning the registered bean definitions. --返回注册的 bean 定义
	 * <p>This method does <i>not</i> register an annotation config processor -- 此方法不注册注释配置处理器
	 * but rather leaves this up to the caller.--而是将其留给调用方
	 * @param basePackages the packages to check for annotated classes --basePackages 用于检查带注释类的包
	 * @return set of beans registered if any for tooling registration purposes (never {@code null}) -- 返回 为工具注册目的注册的 bean 集 (如果有的话)(从不为null)
	 */
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

 接下来看红框的方法:findCandidateComponents(basePackage)

截图:

代码:

/**
	 * Scan the class path for candidate components.-- 扫描类路径以查找候选组件
	 * @param basePackage the package to check for annotated classes -- basePackage 用于检查带注释类的包
	 * @return a corresponding Set of autodetected bean definitions --返回一组相应自动检测 bean 定义
	 */
	public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		}
		else {
			return scanCandidateComponents(basePackage);
		}
	}

 接着看红框方法 scanCandidateComponents(basePackage);

截图:

 代码:

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
            //做了一个常量的拼接,拿到一个路径 classpath*:com/.../*.class
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
            // 查找这个路径下面有没有标注了 @Controller、@Service、@Component 等标注的类,拿到这些类,经过一定的处理之后,将所有的实例对象 BeanDefinition放进 candidates 进行返回
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						if (isCandidateComponent(metadataReader)) {
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
							if (isCandidateComponent(sbd)) {
								if (debugEnabled) {
									logger.debug("Identified candidate component class: " + resource);
								}
								candidates.add(sbd);
							}
							else {
								if (debugEnabled) {
									logger.debug("Ignored because not a concrete top-level class: " + resource);
								}
							}
						}
						else {
							if (traceEnabled) {
								logger.trace("Ignored because not matching any filter: " + resource);
							}
						}
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to read candidate component class: " + resource, ex);
					}
				}
				else {
					if (traceEnabled) {
						logger.trace("Ignored because not readable: " + resource);
					}
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}

到此, @ComponentScan的解析过程到此结束了!

@Import注解的解析过程,其实和@ComponentScan都差不多。

再回到最初的parse()方法,通过parse()方法拿到注解组件类,然后回到第二个重要方法deferredImportSelectorHandler.process()方法

2.2 接着看方法 this.deferredImportSelectorHandler.process();

原截图:

 deferredImportSelectorHandler 方法

截图:

代码:

public void process() {
            // deferredImportSelectors -- 延迟导入选择器
			List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
			this.deferredImportSelectors = null;
			try {
				if (deferredImports != null) {
                    // 延迟导入选择器分组处理程序
					DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
					deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
					deferredImports.forEach(handler::register);
                    //处理分组导入
					handler.processGroupImports();
				}
			}
			finally {
				this.deferredImportSelectors = new ArrayList<>();
			}
		}

 接下来看红框的方法 handler.processGroupImports();

截图:

 代码:

public void processGroupImports() {
            // DeferredImportSelectorGrouping -- 延迟导入选择器分组,这个就是自动配置的导入类
            // 然后会走 getImports() 方法,执行里面的 process() 方法和 selectImports() 方法
			for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
				grouping.getImports().forEach(entry -> {
					ConfigurationClass configurationClass = this.configurationClasses.get(
							entry.getMetadata());
					try {
						processImports(configurationClass, asSourceClass(configurationClass),
								asSourceClasses(entry.getImportClassName()), false);
					}
					catch (BeanDefinitionStoreException ex) {
						throw ex;
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to process import candidates for configuration class [" +
										configurationClass.getMetadata().getClassName() + "]", ex);
					}
				});
			}
		}

调用前面 AutoConfigurationImportSelector.process() 和selectorImports()方法
因为在上面的parse()方法中,因为@Import(AutoConfigurationImportSelector.class)已经把AutoConfigurationImportSelector这个bean注册到 IOC 容器了,已经可以使用。

然后查看 grouping.getImports() 方法

 代码:

/**
		 * Return the imports defined by the group. -- 返回由组定义的导入
		 * @return each import with its associated configuration class -- 返回每个导入及其关联的配置类
		 */
		public Iterable<Group.Entry> getImports() {
			for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
				this.group.process(deferredImport.getConfigurationClass().getMetadata(),
						deferredImport.getImportSelector());
			}
			return this.group.selectImports();
		}

接着看红框的方法 return this.group.selectImports();

截图:

 回到了 DeferredImportSelector 延迟导入选择器接口的内部接口,看下其AutoConfigurationImportSelector 实现类:

 到这里就可以获取到所有jar包下 META-INF/spring.factories 中的所有需 EnableAutoConfiguration的自动配置类

那么到此ConfigurationClassParser.parse()才执行完!!!是不是就结束了呢???
还没有,此时,只是获取到了spring.factories所有需要自动配置的配置类的全限定路径,这些自动配置类还没有真正生效,还没有注册到DefaultListableBeanFactory(IOC容器)的beanDefinitionMap中

 到此 refreshContext() 完成

参考文章:https://blog.csdn.net/weixin_42460087/article/details/112007838

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/638739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高阶复杂网络重建:从时间序列中重建高阶网络

论文链接&#xff1a;https://www.nature.com/articles/s41467-022-30706-9 一、为什么要研究高阶网络&#xff1f; 复杂网络跟我们生活息息相关&#xff0c;例如社交网络的信息传播&#xff0c;疾病的感染扩散和基因调控网络的相互作用等。越来越多的研究突破了传统网络中两…

SSH暴力破解

Linux是开源系统&#xff0c;系统本身因漏洞造成的攻击相对比较少&#xff0c;主要集中在SSH攻击&#xff1b; SSH所采用的加密机制&#xff0c;可以防止数据传输过程中信息泄露&#xff1b; SSH基于用户名密码的身份验证&#xff0c;容易遭受密码暴力破解攻击&#xff1b; S…

上海交通大学计算机考研分析

关注我们的微信公众号 姚哥计算机考研 更多详情欢迎咨询 上海交通大学&#xff08;A&#xff09;考研难度&#xff08;☆☆☆☆☆&#xff09; 上海交通大学电子信息与电气工程学院的前身可溯源至1908年的电机专科&#xff0c;享有中国电气工程师“摇篮”的美称&#xff0c;…

远程线程注入之突破Session0隔离会话

前言 当我们使用远程线程注入将dll注入至系统服务进程中往往会失败&#xff0c;这是因为大多数系统服务都是在Session0中运行的 "Session 0"是Windows操作系统中的一个特殊的会话&#xff0c;专门用于运行系统服务和其他在用户登录之前就需要运行的程序。从Windows…

卷积神经网络CNN(第三次组会)

卷积神经网络 1. 为什么用卷积2. 两个原则3. 参数理解4. 理解卷积 1. 为什么用卷积 2. 两个原则 3. 参数理解 4. 理解卷积

Proteus仿真之IIC通信(AT24C02)

1.IIC通信简介&#xff1a;IIC是一种利用时钟线SCL和数据线SDA进行数据传输的通信协议。IIC的时序图如下所示&#xff1a; 我们需要看懂时序图中开始信号、数据传输、应答信号和停止信号。 开始信号&#xff1a;SCL为高电平时&#xff0c;SDA出现下降沿信号。 数据传输&#…

c++类和对象(封装)

4、类和对象 C面向对象的三大特性为&#xff1a;封装、继承、多态 C认为万事万物都皆为对象&#xff0c;对象上有其属性和行为 例如: 人可以作为对象&#xff0c;属性有姓名、年龄、身高、体重...&#xff0c;行为有走、跑、跳、吃饭、唱歌...车也可以作为对象&#xff0c;属性…

python带你制作自动点赞小程序,让我看看谁还在呆呆的手动点赞

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 知识点: 动态数据抓包 requests发送请求 开发环境: 代码所使用软件工具&#xff1a; python 3.8 >>>>>> 运行代码 pycharm 2022.3 >>>>>> 辅助敲代码 需下载的第三方模块&a…

【微信公众平台对接】有关上传pdf到微信

1、微信文档说明 ps:有关微信的一些文档说明我真的是服了&#xff0c;这个文档&#xff0c;抛出来看的人真的是一头雾水&#xff0c;算了&#xff0c;我也不做过多评判&#xff1b;下面看我调用的示例代码 2、示例代码 /*** 上传pdf* https://api.weixin.qq.com/card/invoice…

HTML+CSS实训——Day13——学习MySQL

前言 已经过去三周了&#xff0c;现在是第四周&#xff0c;之前所有的数据都是在本地的&#xff0c;还没有学到数据库&#xff0c;这周开始使用数据库了。 我自用的是navicat 连接服务器 我们新建一个连接&#xff0c;写上主机和端口号&#xff0c;再写上用户名和密码就可以…

【新版】系统架构设计师 - 计算机系统基础知识【补充】

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 计算机系统基础知识【补充内容】计算机语言多媒体系统工程霍尔的三维结构切克兰德方法并行工程方法综合集成法WSR&#xff08;物理-事理-人理&#xff09;系统方法系统工程生命周期7阶段生命周期方…

23年软件测试前景和出路?新人入行测试怎样走“正确“的路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 现在面试&#xf…

Java IO 学习总结(一)输入流/输出流

前言&#xff1a; 学习IO流&#xff0c;记录并分享。文章如有错误&#xff0c;恳请指正。 Java IO流的类图&#xff1a; 1、什么是 Java IO 流&#xff1f; 数据传输是需要通道的&#xff0c;而IO流就是数据传输的通道。IO流可以形象比喻为运送货物的传输带。运送的货物就是…

电子蜡烛灯单片机开发方案

LED蜡烛灯可以像真正的蜡烛一样发出舒适的闪烁光&#xff0c;具有仿真蜡烛效果&#xff0c;适合在一些聚会或庆祝活动中使用。宇凡微推出的低成本LED蜡烛灯IC方案&#xff0c;根据不同电子蜡烛灯方案&#xff0c;主控芯片推荐使用YF单片机。 LED蜡烛灯是有孩子的家庭很好蜡烛替…

【51单片机疑难杂症】:基于普中科技51单片机-A3型号开发板 ds18b20温度传感器和ds1302时钟芯片(板载)冲突现象的解答

项目场景&#xff1a; 当使用普中科技A3型号&#xff0c;准备开发板载的ds1302和温度ds18b20,出现了两者不能共用的问题&#xff0c;以下是问题记录与解答&#xff0c;大家如果觉得有用&#xff0c;请关注点赞哦。谢谢大家。 问题描述 基于普中科技51单片机-A3型号开发板 ds18b…

js 给图片添加水印

如何在图片上添加水印&#xff1f; 1、把图片或者图片文件转成image元素 2、把转成的image转成canvas 3、在生成的canvas中添加水印 先看效果 1、把图片或者图片文件转成image元素 function urlToImg(url) {return new Promise((resolve, reject) > {const img new Image(…

如何实现在线书签内容替换

书签广泛应用于企业的各种办公自动化业务场景中。例如&#xff1a;在范式合同模板中将甲乙方书签自动替换成具体的公司名称&#xff1b;在红头文件模板中将红头标题书签替换成具体的行政指令&#xff1b;在各种协议模板中将协议日期书签替换为当前日期&#xff1b;等等。 在这…

低代码赛道拥挤 生态聚合成为破局关键

在云计算和移动互联网的强劲推动下&#xff0c;企业数字化转型的步伐正在加速&#xff0c;对于软件应用开发的需求也呈现出爆发式的增长。这样的背景下&#xff0c;低代码平台凭借其独特的优势迅速崛起并引发了业界的广泛关注。 自2020年以来&#xff0c;低代码领域已成为投资…

5年测试岗,自动化测试经验总结(真实)他的测试之路高歌猛进...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 8年测试工程师的自…

软考A计划-2023系统架构师-知识点集锦(2/4)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…