Spring 源码分析衍生篇七 :ConfigurationClassPostProcessor 上篇

一、前言

本文是 Spring源码分析:Spring源码分析七:BeanFactoryPostProcessor 的处理 - invokeBeanFactoryPostProcessors 的衍生文章。主要是因为本人菜鸡,在分析源码的过程中还有一些其他的内容不理解,故开设衍生篇来完善内容以学习。


ConfigurationClassPostProcessor 的分析受篇幅所限,分为上下两篇
上篇 分析 postProcessBeanDefinitionRegistry 方法的调用。
下篇 分析 postProcessBeanFactory 方法的调用。


ConfigurationClassPostProcessor 是非常重要的一个 后处理器。 ConfigurationClassPostProcessor 完成了 配置类的解析和保存。将所有需要注入的bean解析成 BeanDefinition保存到 BeanFactory 中。

1. ConfigurationClassPostProcessor

首先来讲解一下 ConfigurationClassPostProcessor 的结构图如下。
在这里插入图片描述

可见ConfigurationClassPostProcessor 接口实现了BeanDefinitionRegistryPostProcessor(BeanFactory 的后处理器)
PriorityOrdered(设置自己的优先级为最高) 和各种 Aware 接口。

我们这里重点看的是 BeanDefinitionRegistryPostProcessor 接口的两个方法:

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

关于这两个方法的调用时机和作用,我们在之前的文章已经讲过,这里不再赘述。

二 、正文

上面已经提及,本文主要关注 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 方法的解析。所以我们下面来看看 postProcessBeanDefinitionRegistry 方法

	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    
    
		.... 省略部分代码
		// 关键方法,解析 配置类的定义
		processConfigBeanDefinitions(registry);
	}

可以看到 postProcessBeanDefinitionRegistry 方法中并没有处理什么逻辑,真正逻辑在其调用的 processConfigBeanDefinitions 方法中

1. processConfigBeanDefinitions

processConfigBeanDefinitions 方法完成了关于配置类的所有解析。

详细代码如下

	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    
    
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		// 获取已经解析的BeanName
		String[] candidateNames = registry.getBeanDefinitionNames();
		// 遍历BeanName
		for (String beanName : candidateNames) {
    
    
			// 获取BeanDefinition 
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			// 如果bean被解析过,if 属性成立,这里是为了防止重复解析
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
    
    
				if (logger.isDebugEnabled()) {
    
    
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			// ConfigurationClassUtils.checkConfigurationClassCandidate 解析了当前bean是否是配置类,关于其详细内容,后面解析
			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 注解进行排序(如果使用了 @Order 注解的话)
		configCandidates.sort((bd1, bd2) -> {
    
    
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		... 忽略部分代码

		// 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..while 循环解析。因为一个配置类可能引入另一个配置类。
		do {
    
    
			// 开始解析。后面详细分析
			parser.parse(candidates);
			// 这里的校验是校验如果是被 @Configuration修饰且proxyBeanMethods属性为true,则类不能为final。如果@Bean修饰的方法,则必须是可覆盖的.
			// 因为@Configuration(proxyBeanMethods = true) 是需要cglib代理的,所以不能为终态, @Bean也一样
			// 是否需要代码是根据 类或方法上的 @Scope注解指定的,默认都是不代理
			parser.validate();
			// configClasses  保存这次解析出的配置类
			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			// 去除已经解析过的配置类
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
    
    
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			// 注册bean
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			// if 如果程丽丽,说明有bean注册了,则需要解析新的bean
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
    
    
				// 获取新的beanName
				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)) {
    
    
						// 过滤出未解析的bean检测是否是未解析过的配置类
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
    
    
							// 如果是未解析的配置类,则保存到candidates中
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		// 如果 candidates 不为空,则说明有未被解析的配置类,循环解析。
		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
			// for a shared cache since it'll be cleared by the ApplicationContext.
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

这里简单总结一下流程;

  1. 获取已经注册的Bean, 并筛选出配置类,按照@Order 进行排序,得到配置类集合 configCandidates
  2. 调用 parser.parse(candidates); 对配置类进行解析
  3. 调用 this.reader.loadBeanDefinitions(configClasses); 进行配置类的注册
  4. 检验 registry.getBeanDefinitionCount() > candidateNames.length 是否成立。这里由于第三步会将新解析出来的bean进行注册,如果这里成立,则说明有新的配置类完成了注册,获取到新注册的配置类candidateNames。循环从第二步重新解析,直到没有新注入的配置类。

上面解释的可能比较乱,因为我们下面详细去分析几个方法。

1.1 checkConfigurationClassCandidate

processConfigBeanDefinitions 方法中。判断一个类是否是配置类就是通过 checkConfigurationClassCandidate 方法来判断的,那么我们需要看看这个方法中是怎么实现的。

在这个方法里,关键的部分是 给 BeanDefinition 设置了CONFIGURATION_CLASS_ATTRIBUTEfull 或者 lite 设置这两个属性标识,如果一个类满足full或 lite的条件,则会被认为是配置类。需要注意的是,本文所说的配置类即使满足 full 或 lite 条件的类,而不仅仅是被 @Configuration 修饰的类。


首先需要注意的是,在 checkConfigurationClassCandidate 中,配置类的类型分为两种,FullLite,即完整的配置类和精简的配置类。

full 和 lite 设置的规则如下:

  • Full : 即类被 @Configuration 注解修饰 && proxyBeanMethods属性为true (默认为 true)
  • Lite : 被 @Component、@ComponentScan、@Import、@ImportResource 修饰的类 或者 类中有被@Bean修饰的方法。

下面我们来看具体代码:

public static boolean checkConfigurationClassCandidate(
			BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    
    
		// 获取className
		String className = beanDef.getBeanClassName();
		if (className == null || beanDef.getFactoryMethodName() != null) {
    
    
			return false;
		}

		... 忽略部分代码
		
		// 获取bean上的Configuration 注解的属性。如果没有被 @Configuration 修饰 config 则为null
		Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
		// 如果被 @Configuration 修饰 &&  proxyBeanMethods 属性为 true。 @Configuration 的 proxyBeanMethods  属性默认值即为 true。
		if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
    
    
			// 设置 CONFIGURATION_CLASS_ATTRIBUTE 为 full
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
		// 如果被 @Configuration 修饰 &&  isConfigurationCandidate(metadata) = true
		else if (config != null || isConfigurationCandidate(metadata)) {
    
    
			// 设置 CONFIGURATION_CLASS_ATTRIBUTE 为 lite
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
		}
		else {
    
    
			return false;
		}

		// It's a full or lite configuration candidate... Let's determine the order value, if any.
		// 按照@Order 注解排序
		Integer order = getOrder(metadata);
		if (order != null) {
    
    
			beanDef.setAttribute(ORDER_ATTRIBUTE, order);
		}

		return true;
	}

1.1.1. isConfigurationCandidate

在上面的代码中,我们看到 判断是否是 Lite 的关键方法是 isConfigurationCandidate。其代码如下:

	// candidateIndicators  的定义
	private static final Set<String> candidateIndicators = new HashSet<>(8);

	static {
    
    
		candidateIndicators.add(Component.class.getName());
		candidateIndicators.add(ComponentScan.class.getName());
		candidateIndicators.add(Import.class.getName());
		candidateIndicators.add(ImportResource.class.getName());
	}	

	public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    
    
		// Do not consider an interface or an annotation...
		// 不能是接口
		if (metadata.isInterface()) {
    
    
			return false;
		}

		// Any of the typical annotations found?
		// 被 candidateIndicators 中的注解修饰
		for (String indicator : candidateIndicators) {
    
    
			if (metadata.isAnnotated(indicator)) {
    
    
				return true;
			}
		}

		// Finally, let's look for @Bean methods...
		try {
    
    
			// 类中包含被 @Bean 注解修饰的方法
			return metadata.hasAnnotatedMethods(Bean.class.getName());
		}
		catch (Throwable ex) {
    
    
			if (logger.isDebugEnabled()) {
    
    
				logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
			}
			return false;
		}
	}

1.2 parser.parse(candidates);

上面解析了如何判断一个类是否是配置类。也完成了配置类的筛选。那么开始进行配置类的解析,在 processConfigBeanDefinitions 方法中,对配置类的解析也只是一句话完成:

	parser.parse(candidates);

parser.parse(candidates); 的作用是:

  1. 将所有的配置类保存到 ConfigurationClassParser#configurationClasses 集合中

    	private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();
    
  2. 解析注解并赋值给每个 ConfigurationClass 对应的属性。如解析 @Import 注解,并通过如下语句将结果保存到 ConfigurationClass.importBeanDefinitionRegistrars 集合中。

    configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
    

    同样的还有 将@ ImportResource 注解保存到ConfigurationClass.importedResources中,将@Bean 修饰的方法 和接口静态方法保存到ConfigurationClass.beanMethods 中。
    而在之后的 this.reader.loadBeanDefinitions(configClasses); 中才进行了这些属性的进一步处理


下面我们来具体看代码,其代码如下:

	public void parse(Set<BeanDefinitionHolder> configCandidates) {
    
    
		for (BeanDefinitionHolder holder : configCandidates) {
    
    
			BeanDefinition bd = holder.getBeanDefinition();
			try {
    
    
			
				if (bd instanceof AnnotatedBeanDefinition) {
    
    
					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);
			}
		}

		this.deferredImportSelectorHandler.process();
	}

里面的 parse 方法会调用 processConfigurationClass 方法,所以我们直接进入 processConfigurationClass 方法:

	protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    
    
		// 判断是否应该跳过当前类的解析。这里面解析了 @Conditional 注解
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
    
    
			return;
		}
		// 判断是否已经解析过。configurationClasses 中保存着已经解析过的配置类
		// 这里应该是 注入的配置类优先级高于引入的配置类
		// 如果配置类被多次引入则合并属性
		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 = asSourceClass(configClass, filter);
		do {
    
    
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		while (sourceClass != null);
		// 保存解析过的 配置类
		this.configurationClasses.put(configClass, configClass);
	}

额外提一句,this.conditionEvaluator.shouldSkip 中对 @Conditional 注解 注解进行了处理,由于篇幅所限,这里不再展开叙述。

看了这么久的源码,也知道了Spring的套路,方法名以do开头的才是真正做事的方法, 所以我们来看 doProcessConfigurationClass 方法。

@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
    
    
		// 1. 处理 @Component 注解
		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    
    
			// Recursively process any member (nested) classes first
			processMemberClasses(configClass, sourceClass, filter);
		}

		// Process any @PropertySource annotations
		// 2. 处理 @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
		// 3. 处理 @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
				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
		// 4. 处理 @Import 注解
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

		// Process any @ImportResource annotations
		// 5. 处理 @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
		// 6. 处理 @Bean修饰的方法
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
    
    
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
		// 7. 处理其他默认接口方法
		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;
	}

doProcessConfigurationClass 方法中的逻辑很清楚,因为他把大部分的逻辑直接封装成了方法。下面我们就来一个一个分析。

1.2.1 处理 @Component 注解

这里对 @Component 的处理其实是处理配置类的内部类,即如果当前类是被 @Component 修饰,则需要判断其内部类是否需要解析。

		// 首先判断如果配置类被@Component 修饰,则调用processMemberClasses 方法处理
		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    
    
			// Recursively process any member (nested) classes first
			processMemberClasses(configClass, sourceClass, filter);
		}

processMemberClasses 方法的代码如下:
代码逻辑也很简单。即如果配置类中有内部类,则判断其内部类是否是配置类,如果是则递归去解析新发现的内部配置类。

	private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
			Predicate<String> filter) throws IOException {
    
    
		// 获取内部类
		Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
		if (!memberClasses.isEmpty()) {
    
    
			// 如果有内部类,则遍历内部类,判断内部类是否是配置类,如果是,则添加到 candidates 集合中。
			List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
			for (SourceClass memberClass : memberClasses) {
    
    
				// 这里判断的是是否是lite 类型的配置类
				if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
						!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
    
    
					candidates.add(memberClass);
				}
			}
			// 进行排序
			OrderComparator.sort(candidates);
			for (SourceClass candidate : candidates) {
    
    
				// importStack 用来缓存已经解析过的内部类,这里处理循环引入问题
				if (this.importStack.contains(configClass)) {
    
    
					this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
				}
				else {
    
    
					// 解析前入栈,防止循环引入
					this.importStack.push(configClass);
					try {
    
    
						// 递归去解析新发现的配置类
						processConfigurationClass(candidate.asConfigClass(configClass), filter);
					}
					finally {
    
    
						// 解析完毕出栈
						this.importStack.pop();
					}
				}
			}
		}
	}

注:

  1. 判断内部类是否是配置类,这里是检测内部类是否满足lite 的配置类规则,并未校验 full的规则。
  2. 代码中使用了this.importStack 来防止递归引入。避免了A引入B,B又引入A这种无限循环的情况。

1.2.2 处理 @PropertySource 注解

@PropertySource 注解可以引入配置文件使用。在这里进行 @PropertySource 注解的解析

	// 去重后遍历 PropertySource 注解所指向的属性。注意这里有两个注解@PropertySources 和 @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.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
					"]. Reason: Environment must implement ConfigurableEnvironment");
		}
	}

processPropertySource 代码如下,在这里解析每一个@PropertySource 注解属性 :

	private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
    
    
		// 获取 @PropertySource 注解的各个属性
		String name = propertySource.getString("name");
		if (!StringUtils.hasLength(name)) {
    
    
			name = null;
		}
		String encoding = propertySource.getString("encoding");
		if (!StringUtils.hasLength(encoding)) {
    
    
			encoding = null;
		}
		// 获取指向的文件路径
		String[] locations = propertySource.getStringArray("value");
		Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
		boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");

		Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
		PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
				DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
		// 遍历文件路径
		for (String location : locations) {
    
    
			try {
    
    
				//  根据路径获取到资源文件并保存到environment 中
				// 解决占位符,获取真正路径
				String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
				Resource resource = this.resourceLoader.getResource(resolvedLocation);
				//保存 PropertySource 到 environment 中
				addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
			}
			catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
    
    
				// Placeholders not resolvable or resource not found when trying to open it
				if (ignoreResourceNotFound) {
    
    
					if (logger.isInfoEnabled()) {
    
    
						logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
					}
				}
				else {
    
    
					throw ex;
				}
			}
		}
	}

1.2.3 处理 @ComponentScan 注解

@componentScans 指定自动扫描的路径。

		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		// 如果当前配置类被 @componentScans 或 @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
				// 遍历扫描出来的bean
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
    
    
				// 获取原始的bean的定义
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
    
    
						bdCand = holder.getBeanDefinition();
					}
					// 检测如果是配置类,则递归调用 parse 解析。
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
    
    
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

这里需要注意 :

  1. this.componentScanParser.parse 方法完成了指定路径下的bean的扫描,这里不再具体分析。
  2. 这里校验是否是配置类调用的是 checkConfigurationClassCandidate 方法,即校验了 full或lite的规则,和 处理 @Component 中的内部类的规则并不相同。
  3. 没错,又是递归,如果扫描到的bean中发现了新的配置类,则递归去解析。

1.2.4 处理 @Import、ImportSelector、 ImportBeanDefinitionRegistrar

这里可以看到,该方法处理的包括 @Import、ImportSelector、 ImportBeanDefinitionRegistrar。
这三个注解或接口都可以完成Bean的引入功能。


我们直接来看 processImports 方法,注释都比较清楚 :

	private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {
    
    
		// 如果 没有需要引入的直接返回
		if (importCandidates.isEmpty()) {
    
    
			return;
		}
		// 检测是否是循环引用。
		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
    
    
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
    
    
			// 解析前先入栈,防止循环引用
			this.importStack.push(configClass);
			try {
    
    
				for (SourceClass candidate : importCandidates) {
    
    
					// 判断是否是ImportSelector类型。ImportSelector 则需要调用selectImports 方法来获取需要注入的类。
					if (candidate.isAssignable(ImportSelector.class)) {
    
    
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class<?> candidateClass = candidate.loadClass();
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
    
    
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
						if (selector instanceof DeferredImportSelector) {
    
    
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
    
    
						// 调用 selectImports 方法获取需要引入的类,并递归再次处理。
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
							// 递归解析
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
					// 如果是 ImportBeanDefinitionRegistrar 类型,则委托它注册其他bean定义
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
    
    
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						Class<?> candidateClass = candidate.loadClass();
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
    
    
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
						// 否则递归处理需要引入的类。
						processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
					}
				}
			}
			catch (BeanDefinitionStoreException ex) {
    
    
				throw ex;
			}
			catch (Throwable ex) {
    
    
				throw new BeanDefinitionStoreException(
						"Failed to process import candidates for configuration class [" +
						configClass.getMetadata().getClassName() + "]", ex);
			}
			finally {
    
    
				this.importStack.pop();
			}
		}
	}

1.2.5 处理 @ImportResource 注解

@ImportResource 就显得很简单了,直接保存到 configClass 中

	// Process any @ImportResource annotations
		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);
			}
		}

1.2.6 处理 @Bean修饰的方法

@Bean 也很简单了,直接保存到 configClass 的中

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

1.2.7 处理接口默认方法

这里也是将接口的非抽象接口保存到 configClass 中

	/**
	 * Register default methods on interfaces implemented by the configuration class.
	 */
	private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
    
    
		for (SourceClass ifc : sourceClass.getInterfaces()) {
    
    
			Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
			for (MethodMetadata methodMetadata : beanMethods) {
    
    
				if (!methodMetadata.isAbstract()) {
    
    
					// A default method or other concrete method on a Java 8+ interface...
					configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
				}
			}
			processInterfaces(configClass, ifc);
		}
	}

1.2.8 处理父类

如果存在父类,则将父类返回。

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

这里这么处理是解析到最上层的父类。这里理一下调用顺序:parse -> processConfigurationClass -> doProcessConfigurationClass 。而 doProcessConfigurationClass 有如下一个循环,只有sourceClass = null 才会跳出循环。当 configClass 没有满足上面判断条件的父类时,才会返回null

	SourceClass sourceClass = asSourceClass(configClass, filter);
		do {
    
    
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		while (sourceClass != null);
	this.configurationClasses.put(configClass, configClass);

1.3 this.reader.loadBeanDefinitions(configClasses);

上面也说了,在parser.parse(candidates); 方法中,将各种注解的属性值都解析了处来,并保存到了 configClass的各种属性中。
而在 this.reader.loadBeanDefinitions(configClasses); 中才真正处理了这些属性。所以我们接下来看看loadBeanDefinitions 的处理流程。


loadBeanDefinitions 遍历了每一个ConfigurationClass ,通过loadBeanDefinitionsForConfigurationClass 方法处理。

	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    
    
		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
		for (ConfigurationClass configClass : configurationModel) {
    
    
			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
		}
	}

所以我们来看看 loadBeanDefinitionsForConfigurationClass 的实现。
可很清楚的看到,每个部分的解析都封装到了不同的方法中。

private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    
    
		// 判断是否应该跳过
		if (trackedConditionEvaluator.shouldSkip(configClass)) {
    
    
			String beanName = configClass.getBeanName();
			if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
    
    
				this.registry.removeBeanDefinition(beanName);
			}
			this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
			return;
		}
		// 如果配置是被引入的
		if (configClass.isImported()) {
    
    
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		// 遍历配置类中的所有方法
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    
    
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
		// 加载 通过 @ImportResource 的 获取的bean
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		// 加载 通过 @Import 的 获取的bean
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}


下面 我们来详细看看每个方法。

1.3.1 registerBeanDefinitionForImportedConfigurationClass

这一步的工作很简单,就是将引入的配置类注册为 BeanDefinition。

	private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
    
    
		AnnotationMetadata metadata = configClass.getMetadata();
		AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
		
		ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
		configBeanDef.setScope(scopeMetadata.getScopeName());
		String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
		AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
		// 创建代理,根据 scopeMetadata 的代理模式。
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		// 注册了BeanBeanDefinition 。这里将BeanDefinition保存到了 DefaultListableBeanFactory#beanDefinitionMap 中
		this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
		configClass.setBeanName(configBeanName);

		if (logger.isTraceEnabled()) {
    
    
			logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
		}
	}

这里需要注意的是 AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 根据scopeMetadata 的代理模式创建了代理。代理模式有四种,分别为

  • DEFAULT : 默认模式。默认等同于NO
  • NO : 不使用代理
  • INTERFACES : Jdk 动态代理
  • TARGET_CLASS : Cglib代理

applyScopedProxyMode 方法中 通过获取ScopeMetadata.getScopedProxyMode() 来判断使用什么代理方式。而ScopeMetadata 的代理方式 是在创建 scopeMetadata 的过程中,获取类上面的@ScopeproxyMode 属性来指定的。

ScopeMetadata scopeMetadata =  scopeMetadataResolver.resolveScopeMetadata(configBeanDef);

resolveScopeMetadata 方法如下

	protected Class<? extends Annotation> scopeAnnotationType = Scope.class;
	@Override
	public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
    
    
		ScopeMetadata metadata = new ScopeMetadata();
		if (definition instanceof AnnotatedBeanDefinition) {
    
    
			AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
			// 获取 @Scope 注解
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
					annDef.getMetadata(), this.scopeAnnotationType);
			if (attributes != null) {
    
    
			
				metadata.setScopeName(attributes.getString("value"));
				// 获取 @Scope 的proxyMode属性
				ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
				if (proxyMode == ScopedProxyMode.DEFAULT) {
    
    
					proxyMode = this.defaultProxyMode;
				}
				// 设置 scopedProxyMode 属性,后面根据此属性判断使用什么代理方式
				metadata.setScopedProxyMode(proxyMode);
			}
		}
		return metadata;
	}

1.3.2 loadBeanDefinitionsForBeanMethod

具体代码如下,基本上就是解析各种注解,创建对应的 BeanDefinition 并注册。

	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
    
    
		ConfigurationClass configClass = beanMethod.getConfigurationClass();
		MethodMetadata metadata = beanMethod.getMetadata();
		String methodName = metadata.getMethodName();

		// Do we need to mark the bean as skipped by its condition?
		// 是否应该跳过
		if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
    
    
			configClass.skippedBeanMethods.add(methodName);
			return;
		}
		if (configClass.skippedBeanMethods.contains(methodName)) {
    
    
			return;
		}
		// 获取被 @Bean修饰的方法
		AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
		Assert.state(bean != null, "No @Bean annotation attributes");

		// Consider name and any aliases
		// 获取别名
		List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
		String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

		// Register aliases even when overridden
		// 注册别名
		for (String alias : names) {
    
    
			this.registry.registerAlias(beanName, alias);
		}

		// Has this effectively been overridden before (e.g. via XML)?
		// 判断是否已经被定义过
		if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
    
    
			if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
    
    
				throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
						beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
						"' clashes with bean name for containing configuration class; please make those names unique!");
			}
			return;
		}
		// 定义配置类的  BeanDefinition
		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
		beanDef.setResource(configClass.getResource());
		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
		// 处理静态 @Bean 方法和非静态
		if (metadata.isStatic()) {
    
    
			// static @Bean method
			if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
    
    
				beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
			}
			else {
    
    
				beanDef.setBeanClassName(configClass.getMetadata().getClassName());
			}
			beanDef.setUniqueFactoryMethodName(methodName);
		}
		else {
    
    
			// instance @Bean method
			beanDef.setFactoryBeanName(configClass.getBeanName());
			beanDef.setUniqueFactoryMethodName(methodName);
		}

		if (metadata instanceof StandardMethodMetadata) {
    
    
			beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
		}
		// 设置构造模式 构造注入
		beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		// 设置跳过属性检查
		beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
				SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
		// 处理通用的注解: @Lazy、@Primary、@DependsOn、@Role、@Description。设置到 BeanDefinition 中
		AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
		// 获取注解的其他属性并设置到 BeanDefinition
		Autowire autowire = bean.getEnum("autowire");
		if (autowire.isAutowire()) {
    
    
			beanDef.setAutowireMode(autowire.value());
		}

		boolean autowireCandidate = bean.getBoolean("autowireCandidate");
		if (!autowireCandidate) {
    
    
			beanDef.setAutowireCandidate(false);
		}

		String initMethodName = bean.getString("initMethod");
		if (StringUtils.hasText(initMethodName)) {
    
    
			beanDef.setInitMethodName(initMethodName);
		}

		String destroyMethodName = bean.getString("destroyMethod");
		beanDef.setDestroyMethodName(destroyMethodName);

		// Consider scoping
		ScopedProxyMode proxyMode = ScopedProxyMode.NO;
		// 处理方法上的 @Scope 注解
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
		if (attributes != null) {
    
    
			beanDef.setScope(attributes.getString("value"));
			proxyMode = attributes.getEnum("proxyMode");
			if (proxyMode == ScopedProxyMode.DEFAULT) {
    
    
				proxyMode = ScopedProxyMode.NO;
			}
		}

		// Replace the original bean definition with the target one, if necessary
		// 如果有必要,替换掉旧的BeanDefinition
		BeanDefinition beanDefToRegister = beanDef;
		if (proxyMode != ScopedProxyMode.NO) {
    
    
			BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
					new BeanDefinitionHolder(beanDef, beanName), this.registry,
					proxyMode == ScopedProxyMode.TARGET_CLASS);
			beanDefToRegister = new ConfigurationClassBeanDefinition(
					(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
		}

		if (logger.isTraceEnabled()) {
    
    
			logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
					configClass.getMetadata().getClassName(), beanName));
		}
		// 注册BeanDefinition
		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
	}

这里会为 @Bean修饰的方法创建出一个 ConfigurationClassBeanDefinition注册到 Spring容器中。在后面的Bean实例化过程中。会在 AbstractAutowireCapableBeanFactory#createBeanInstance 方法中有如下两句。

		if (mbd.getFactoryMethodName() != null) {
    
    
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

@Bean的修饰的方法会调用instantiateUsingFactoryMethod 方法,通过反射调用方法,并将反射结果注入到Spring容器中,完成 @Bean注解的功能。

1.3.3 loadBeanDefinitionsFromImportedResources

loadBeanDefinitionsFromImportedResources 从导入的资源加载Bean定义。即通过解析 @ImportResource 注解引入的资源文件,获取到BeanDefinition 并注册。

private void loadBeanDefinitionsFromImportedResources(
			Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
    
    

		Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();
		// 遍历引入的资源文件
		importedResources.forEach((resource, readerClass) -> {
    
    
			// Default reader selection necessary?
			if (BeanDefinitionReader.class == readerClass) {
    
    
				// 处理 .groovy 类型文件
				if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
    
    
					// When clearly asking for Groovy, that's what they'll get...
					readerClass = GroovyBeanDefinitionReader.class;
				}
				else {
    
    
					// Primarily ".xml" files but for any other extension as well
					// 这里使用 XmlBeanDefinitionReader 类型来解析
					readerClass = XmlBeanDefinitionReader.class;
				}
			}
			// 从缓冲中获取
			BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
			// 如果缓存中没有,则创建一个 reader 用于 resource 的解析。
			if (reader == null) {
    
    
				try {
    
    
					// Instantiate the specified BeanDefinitionReader
					reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
					// Delegate the current ResourceLoader to it if possible
					if (reader instanceof AbstractBeanDefinitionReader) {
    
    
						AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
						abdr.setResourceLoader(this.resourceLoader);
						abdr.setEnvironment(this.environment);
					}
					readerInstanceCache.put(readerClass, reader);
				}
				catch (Throwable ex) {
    
    
					throw new IllegalStateException(
							"Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
				}
			}

			// TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
			// 解析resource资源中的内容
			reader.loadBeanDefinitions(resource);
		});
	}

1.3.4 loadBeanDefinitionsFromRegistrars

loadBeanDefinitionsFromRegistrars 方法注册了了@Import 注解引入的内容。这里很简单,不再赘述。

	private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
    
    
		registrars.forEach((registrar, metadata) ->
				registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
	}

三、总结

从目前我看到的来说(虽然也没看过几个),有两个后处理器非常重要:

  • ConfigurationClassPostProcessor : 即本文解析的这个后处理器。虽然仅仅是上篇,但是其作用已经非常清楚了。ConfigurationClassPostProcessor 解析配置类(这里的配置类不仅仅局限于@Configuration 注解,还包括 @Import@ImportResource 等注解),将解析到的需要注入到Spring容器中的bean的BeanDefinition保存起来。在后面的bean 初始化都需要BeanDefinition。

  • AutowiredAnnotationBeanPostProcessor : 之前解析过。完成了 Bean所依赖的属性的注入。 解析bean中的 需要自动注入的bean @Autowired 和 @Inject @Value注解。具体请看:Spring源码分析衍生篇五:AutowiredAnnotationBeanPostProcessor

    简单来说 ConfigurationClassPostProcessor 完成了 Bean的扫描与解析, AutowiredAnnotationBeanPostProcessor 完成了Bean 属性的注入


本文只分析了 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 方法,对于ConfigurationClassPostProcessor#postProcessBeanFactory 方法的分析则放在后篇,这里简单的说明 ConfigurationClassPostProcessor#postProcessBeanFactory 方法通过cglib动态代理,完成了 对 @Bean修饰方法的代理,以确保其正确语义。


以上:内容部分参考
《Spring源码深度解析》
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/106558290