【Spring源代码阅读之四】ConfigurationClassPostProcessor类postProcessBeanDefinitionRegistry()处理配置类流程

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry处理配置类流程

  • 导言
  • 导图
  • ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
  • processConfigBeanDefinitions
    • ConfigurationClassUtils#isFullConfigurationClass()
    • ConfigurationClassUtils#isLiteConfigurationClass
    • ConfigurationClassParser#parse
      • ConfigurationClassParser#parse
      • ConfigurationClassParser#processConfigurationClass
        • ConfigurationClassParser#doProcessConfigurationClass

导言

ConfigurationClassPostProcessor类实现了BeanDefinitionRegistryPostProcessor接口
在执行refresh()方法时会查找容器中所有实现了BeanDefinitionRegistryPostProcessor接口的类并进行调用
本文章只讲流程,之后两篇文章会讲具体处理

导图

在这里插入图片描述

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

/**
 * 解析配置类中的配置从而可将更多的类加载到Spring容器中
 * 方法是在AbstractApplicationContext#refresh()的invokeBeanFactoryPostProcessors()中调用的(调用链请自行查找)
 * @param registry 此参数就是DefaultListableBeanFactory实例(此类实现了BeanDefinitionRegistry接口)
 */
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	/**
	 * 根据BeanDefinitionRegistry,生成registryId并做去重判断,避免重复解析
	 */
	int registryId = System.identityHashCode(registry);
	if (this.registriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
	}
	if (this.factoriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called on this post-processor against " + registry);
	}
	this.registriesPostProcessed.add(registryId);

	/**
	 * 实质性做解析的方法
	 */
	processConfigBeanDefinitions(registry);
}

processConfigBeanDefinitions

/**
 * 解析配置类中的配置注解
 */
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	/**
	 * 获取所有已经注册的BeanDefinition名称
	 * @see DefaultListableBeanFactory#getBeanDefinitionNames()
	 */
	String[] candidateNames = registry.getBeanDefinitionNames();

	/**
	 * 根据BeanDefinition的name遍历取出BeanDefinition
	 * 如果BeanDefinition被标识了full或者lite,则证明被处理过,跳过不再处理
	 * 否则判断是否是配置类,是的话就加入配置类处理集合
	 */
	for (String beanName : candidateNames) {
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
				ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
			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
	/**
	 * 如果处理集合为空则没有解析的类
	 */
	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
	/**
	 * registry=DefaultListableBeanFactory实例,类型判断正确,
	 * 如果没有设置BeanNameGenerator(可在setBeanNameGenerator()方法中设置),localBeanNameGeneratorSet属性为false
	 * 再从工厂中获取注册到工厂中的BeanNameGenerator,获取到则赋值否则跳过
	 * 本类中已经在变量创建时就实例化了如下两个属性
	 */
	SingletonBeanRegistry sbr = null;
	if (registry instanceof SingletonBeanRegistry) {
		sbr = (SingletonBeanRegistry) registry;
		if (!this.localBeanNameGeneratorSet) {
			BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(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
	/**
	 * 实例化ConfigurationClassParser解析配置类,此类提供解析功能
	 */
	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
		/**
		 * 如果读取器没有实例化,则实例化配置类BeanDefinition读取器并进行加载BeanDefinition添加到已解析集合中
		 */
		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();

		/**
		 * 如果registry中注册的BeanDefinition的数量 > 之前获得的BeanName数量
		 * (BeanDefinitionName数量=BeanDefinition的数量)
		 * 证明在之前的解析过程中有新的类增加,需要对其进行解析
		 */
		if (registry.getBeanDefinitionCount() > candidateNames.length) {
			/**
			 * 获取已注册的BeanDefinitionNames
			 */
			String[] newCandidateNames = registry.getBeanDefinitionNames();
			/**
			 * 将之前获取的BeanDefinitionNames由数组转变为set集合,好做判断
			 */
			Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
			/**
			 * 已处理类名称集合,通过已解析结合获取
			 */
			Set<String> alreadyParsedClasses = new HashSet<>();
			for (ConfigurationClass configurationClass : alreadyParsed) {
				alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
			}
			/**
			 * 遍历所有的BeanDefinitionNames
			 * 如果之前取出的BeanDefinitionNames不包含此Name
			 * 且 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));
					}
				}
			}
			/**
			 * 更新最新的name集合给变量
			 */
			candidateNames = newCandidateNames;
		}
	}
	while (!candidates.isEmpty());

	// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
	/**
	 * 注册一个支持@Configuration注解类的解析Bean,从ConfigurationClassParser类中获取,此Bean在全局变量就实例化了
	 * 并且获取的解析Bean在上面的代码调用链中全程参与了@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
		// for a shared cache since it'll be cleared by the ApplicationContext.
		((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
	}
}

ConfigurationClassUtils#isFullConfigurationClass()

private static final String CONFIGURATION_CLASS_FULL = "full";
/**
 * 查看BeanDefinition是否被标识为一个全配置类
 */
public static boolean isFullConfigurationClass(BeanDefinition beanDef) {
	return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
}

ConfigurationClassUtils#isLiteConfigurationClass

private static final String CONFIGURATION_CLASS_LITE = "lite";
/**
 * 查看BeanDefinition是否被标识为一个半配置类
 */
public static boolean isLiteConfigurationClass(BeanDefinition beanDef) {
	return CONFIGURATION_CLASS_LITE.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
}

ConfigurationClassParser#parse

/**
 * 对配置类集合遍历依次解析,其中配置类对应的不同BeanDefinition执行不同解析方式解析
 */
public void parse(Set<BeanDefinitionHolder> configCandidates) {
	this.deferredImportSelectors = new LinkedList<>();

	for (BeanDefinitionHolder holder : configCandidates) {
		BeanDefinition bd = holder.getBeanDefinition();
		try {
			/**
			 * 注解BeanDefinition进行获取元信息进行解析
			 */
			if (bd instanceof AnnotatedBeanDefinition) {
				parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
			}
			/**
			 * 抽象BeanDefinition并且存在Class(即是由类转变的BeanDefinition)则直接获取Class进行解析
			 */
			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);
		}
	}

	/**
	 * 处理延迟加载的ImportSelector
	 */
	processDeferredImportSelectors();
}

ConfigurationClassParser#parse

/**
 * 对于BeanDefinition对应的类是注解类型的进行创建ConfigurationClass进行解析
 */
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
	processConfigurationClass(new ConfigurationClass(metadata, beanName));
}

ConfigurationClassParser#processConfigurationClass

/**
 * 解析配置类
 */
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
	/**
	 * 判断配置类是否满足加载条件
	 */
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
		return;
	}

	/**
	 * 从配置类处理Map中取出对象
	 */
	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.
			// 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 sourceClass = asSourceClass(configClass);
	do {
		/**
		 * 进行配置类的处理
		 */
		sourceClass = doProcessConfigurationClass(configClass, sourceClass);
	}
	while (sourceClass != null);

	/**
	 * 存放扫描处理完成的BeanDefinition
	 * 交由ConfigurationClassPostProcessor进行统一处理
	 */
	this.configurationClasses.put(configClass, configClass);
}
ConfigurationClassParser#doProcessConfigurationClass
/**
 * 开始处理配置类的过程,处理过程很复杂
 */
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
		throws IOException {

	// Recursively process any member (nested) classes first
	/**
	 * 处理内部类
	 */
	processMemberClasses(configClass, sourceClass);

	// Process any @PropertySource annotations
	/**
	 * 解析@PropertySources和@PropertySource注解,遍历处理
	 * PropertySources的value参数就是PropertySource数组
	 */
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class,
			org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			/**
			 * 处理@PropertySource注解
			 */
			processPropertySource(propertySource);
		}
		else {
			logger.warn("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);
	/**
	 * 如果存在ComponentScan注解 且 符合加载到容器中的条件
	 * 则进入方法体进行遍历解析
	 */
	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
			/**
			 * 执行扫描
			 */
			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,如果没有最原始的,则使用现在的这个BeanDefinition
				 */
				BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
				if (bdCand == null) {
					bdCand = holder.getBeanDefinition();
				}
				/**
				 * 判断BeanDefinition对应的类是否是一个配置类,如果是的话就对其进行解析
				 */
				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);
	/**
	 * 如果存在@ImportResource注解,则进行解析
	 * 注意:这里并没有处理,而是放入了配置类的一个Map集合中后续处理
	 */
	if (importResource != null) {
		/**
		 * 获得配置源的路径
		 */
		String[] resources = importResource.getStringArray("locations");
		/**
		 * 获得配置源使用的BeanDefinition读取器
		 */
		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
		/**
		 * 遍历处理,因为配置源路径可以写多个,是一个数组
		 */
		for (String resource : resources) {
			/**
			 * 对路径中的$占位符做解析,替换成代表的值
			 */
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			/**
			 * 添加到@ImportResource注解所在配置类构建的configClass对象的Map集合中
			 */
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

	// Process individual @Bean methods
	/**
	 * 解析配置类中方法上的@Bean注解
	 */
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	/**
	 * 将含有@Bean注解的方法云信息保存到集合中待后续处理
	 */
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// Process default methods on interfaces
	/**
	 * 处理接口中含有@Bean注解的方法
	 */
	processInterfaces(configClass, sourceClass);

	// Process superclass, if any
	/**
	 * 这里是判断配置类有没有父类,这里一定会进,因为所有的类的父类是Object
	 * 注意:读完代码的处理逻辑,你会发现,配置类的父类也可以当做配置类进行解析处理,父类也能有注解
	 */
	if (sourceClass.getMetadata().hasSuperClass()) {
		/**
		 * 获得父类的全限定名,不为空且不是以java开头的(即不是JDK里的)且不在父类处理集合中,则可以解析父类
		 * 会将父类转化为SourceClass并返回进行处理,所以在上层方法中使用了while循环
		 */
		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
	/**
	 * 在处理完成后并且没有需要处理的父类则返回null,那么这个类就可以放入到一个集合中存储等待注册进容器
	 */
	return null;
}

你可能感兴趣的:(spring源代码,java,spring,spring,boot,bean)