11-Spring源码解析之refresh(4)——invokeBeanFactoryPostProcessors(2)

Spring版本:<version>5.2.1.RELEASE</version>

上一篇:10-Spring源码解析之refresh(4)——invokeBeanFactoryPostProcessors(1)

上一篇还遗留了两个问题,这两个问题非常重要

  • invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);PriorityOrdered) 2-3节介绍

    • ConfigurationClassPostProcessor类如何解析@Configuration注解类
  • invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); 4节介绍

    • ConfigurationClassPostProcessor类如何增强配置类

那么下面我们就一步一步看它是如何做这两件事情的。这里有必要提到一个非常重要的类了:ConfigurationClassPostProcessor

1. ConfigurationClassPostProcessor的类结构

想要了解一个类,那当然首当其冲应该看它所实现的接口和父类:

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
		PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware

接着为了更只管的看到这些类,我们来看看这些类的类结构吧
在这里插入图片描述

接下来,我们就要进入上一篇遗留下来的第一个问题了。看一下invokeBeanFactoryPostProcessors在调用 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);PriorityOrdered)时所作的工作!

2. invokeBeanDefinitionRegistryPostProcessors方法

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

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}

从上一篇文章中,我们可以知道,进入这个方法的postProcessors只有一个,即ConfigurationClassPostProcessor类型的Bean。因此在上面代码中执行postProcessor.postProcessBeanDefinitionRegistry(registry);时,会走到ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法中。我们进入该方法。

	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	 	// 给registry生成一个全局唯一ID。防止重复
		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);
		//  进行BeanDefinition的加载。
		// 3.节 具体介绍
		processConfigBeanDefinitions(registry);
	}

3. processConfigBeanDefinitions方法

下面我们就开始对传入的配置类进行注解解析了。这里的配置类即:启动项目的时候传入的类:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig_AOP.class);

从上述代码可以看出本项目中的配置类为:MainConfig_AOP

我们回来继续分析processConfigBeanDefinitions的实现方式

	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		// 获取已经注册到beanFactory中的beanDefinition。
		// 当前有以下6个(5个内置类+1个配置类),具体参见上篇文章1.节
		// internalConfigurationAnnotationProcessor
		// internalAutowiredAnnotationProcessor
		// internalCommonAnnotationProcessor
		// internalEventListenerProcessor
		// internalEventListenerFactory
		// mainConfig_AOP
		String[] candidateNames = registry.getBeanDefinitionNames();

//-------------------------------------------【功能一】-------------------------------------------
		// 找到上面6个BeanDenition中是带有@Configuration的类, 实际就是找出internalConfigurationAnnotationProcessor
		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);
				}
			}
			// 检查是否是@Configuration的类,如果是就将其放入到configCandidates变量中。
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// 如果没有@Configuration的类,直接返回
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
		// @Configuration的类是可以有顺序的,按照顺序进行排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// 我们可以更改scan和import的方式,如果没有更改默认为:扫描为首字母小写,import为全类名
		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();
		}
		
//-------------------------------------------【功能二】-------------------------------------------
		// 解析每一个被注解 @Configuration 的类
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		// 装载已经处理过的配置类,最大长度为:configCandidates.size()
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			// 核心方法 : 解析配置类,找到配置类中的@Bean @Import @Scan类信息
			// 将这些信息放入到ConfigurationClass中
			// -----【1】----- 3.1节 具体介绍
			parser.parse(candidates);
			// 校验,配置类不能是final类型的,因为在后面需要使用CGLIB生成代理类
			parser.validate();

			// 得到所有已经需要解析的类,【1】中会给出图片
			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 @Import @Scan类信息注册为BeanDefinition
			// -----【2】----- 3.2节 具体介绍
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			// 如果registry中注册的bean的数量 大于 之前获得的数量,
			// 则意味着在解析的类中还引入类其他的注解类,那么就需要对新引入的类进行解析
			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
		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();
		}
	}

根据以上代码,可以知道上述代码实现了三个功能:

  • 【功能一】
    • 从6个BeanDenition中找到中是带有@Configuration类的BeanDefinition
  • 【功能二】
    • 通过执行parser.parse(candidates);解析配置类,即将配置类中标注@Bean@Import等的类找出来
  • 【功能三】
    • 通过执行this.reader.loadBeanDefinitions(configClasses);将功能二中找到的注解类转换为BeanDefinition,并将其注册到beanFactory

3.1. parser.parse(candidates) 解析配置类

	public void parse(Set<BeanDefinitionHolder> configCandidates) {
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				// 由于当前是使用注解驱动,因此当前配置类属于AnnotatedBeanDefinition
				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();
	}

由于当前项目使用的是注解驱动,所以进入AnnotatedBeanDefinition下面的parse方法。这个方法体如下:

	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName));
	}

它会将传入的metadatabeanName封装成ConfigurationClass,然后将封装好后的ConfigurationClass作为参数传入processConfigurationClass中。那么我们继续看processConfigurationClass方法做了哪些操作。

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

		// 如果这个配置类已经存在了,后面又被@Import进来了,会做属性合并
		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);
		do {
//-------------------------------------------【功能一】-------------------------------------------	
			// -----【1】----- 这个方法是核心方法 3.1.1 中详细介绍
			// 解析配置类
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);
//-------------------------------------------【功能二】-------------------------------------------	
		this.configurationClasses.put(configClass, configClass);
	}

以上方法做了两个事情:

  • 【功能一】sourceClass = doProcessConfigurationClass(configClass, sourceClass); -> 3.1.1 具体介绍

    • 解析配置类
    • 并将解析的结果放到configClass中保存
  • 【功能二】this.configurationClasses.put(configClass, configClass); -> 3.1.2 具体介绍

    • 将解析之后的结果放到一个LinkedHashMap中保存
3.1.1 sourceClass = doProcessConfigurationClass(configClass, sourceClass);解析配置类
	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {
		
		// 查看内部类
		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// 先递归地处理内部类, 本项目没有增加内部类,因此暂时先不分析这一块的内容,后续再增加
			processMemberClasses(configClass, sourceClass);
		}

		// 处理每个 @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");
			}
		}

		// 处理每个 @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) {
				// 配置类中注解了@ComponentScan, 因此现在立刻执行扫描,获取其中的BeanDefinition
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// 对ComponentScan得到的BeanDefinition进行检查,看里面是否有需要处理的配置类,有的话进行处理
				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());
					}
				}
			}
		}


		// 处理每个 @Import 注解,将这个注解的类放到configClass的importBeanDefinitionRegistrars中
		// 先调用 getImports(),获取sourceClass上所有@Import注解的value
		processImports(configClass, sourceClass, getImports(sourceClass), true);

		// 处理每个 @ImportResource 注解
		// 本项目中因为使用的是AOP的例子,因此有一个@Import,
		// 即在处理@EnableAspectJAutoProxy注解的时候,引入的@Import(AspectJAutoProxyRegistrar.class)
		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);
			}
		}

		// 处理每个 @Bean 注解
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
		processInterfaces(configClass, sourceClass);

		// 处理父类
		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;
	}

以上代码显示ConfigurationClassParser类的doProcessConfigurationClass方法主要做的事情。按照顺序依次为:

  • [1] 内部配置类:找到配置类中的内部配置类,若有内部配置类,对内部配置类进行递归解析
  • [2] @PropertySource:这个暂时我还没有用到,以后用到再补充
  • [3] @ComponentScan:这里扫描到的Bean,就直接register注册了!!所以在@ComponentScan注解中的类的注册时机是非常早的!要早于其他的注解所标注的类。(通过ClassPathBeanDefinitionScanner去的doScan方法去扫描注册!!)
  • [4] @Import:分三种情况:
    • 【情况一】:普通类 放到 ConfigurationClass中保存
    • 【情况二】:实现了ImportSelector:放在ConfigurationClass中保存。若实现DeferredImportSelector会在ConfigurationClassdeferredImportSelectorHandler属性保存
    • 【情况三】:实现了ImportBeanDefinitionRegistrar,放在ConfigurationClass类的importBeanDefinitionRegistrars属性中。(AOPAspectJAutoProxyRegistrar就属于这一类)

在这里插入图片描述

  • [5] @ImportResource:导入XML文件。放在ConfigurationClass类的importedResources属性中
  • [6] @Bean:配置类的方法上标注@Bean的方法。放在ConfigurationClass类的beanMethods属性中
    • 本文中在配置文件中写了2个Bean注解,因此在执行完这个方法的时候,可以看到ConfigurationClass类的beanMethods属性中有2个类。
@Configuration
@EnableAspectJAutoProxy
public class MainConfig_AOP {
    @Bean
    public MathCalculator calculator() {
        return new MathCalculator();
    }

    @Bean
    public LogAspects logAspects() {
        return new LogAspects();
    }
}

在这里插入图片描述

  • [7] processInterfaces:处理配置类的接口的default方法
  • [8] 处理父类:如果父类也是配置文件,则继续处理,直到父类全部处理完
  • [9] return null:全部处理完成后,返回null

执行到这里,我们得到了项目中完整的ConfigurationClass,它的beanNames为配置类的名字,它有两个beanMethods, 有一个importBeanDefinitionRegistrars(因为当前项目的例子是AOP的例子)。现在我们可以回溯到3.节中,我们已经执行完了3.节的【功能二】部分,下面我们继续来看3. 节【功能三】是如何实现的。

3.2 this.reader.loadBeanDefinitions(configClasses) 将注解转变为beanDefinition

执行到这里,我们已经拿到了ConfigurationClass,它里面包含了配置类的所有解析注解内容,但是还没有把这些信息注册到beanFactory,这一步我们就是将configClasses中的信息转变为beanDefintiion,然后放到beanFacttory中。现在我们先看看目前位置beanFacttory中的beanDefintiion都有什么。
在这里插入图片描述
还是之前的那些beanDefintiion。注意:如果我们在配置类中有@Import注解,那么此时:beanDefintiion中还会有@Import注解对应的beanDefintiion(原因在3.1节有介绍)。我们继续向下分析。

	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
		// 找到项目中所有@Configuration注解标注的类
		for (ConfigurationClass configClass : configurationModel) {
			// 根据ConfigurationClass来注册BeanDefinition
			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
		}
	}

接下来我们看一下它是如何通过ConfigurationClas来注册BeanDefinition的吧

	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()) {
			// 处理@Import的配置类
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			// 这里处理配置类中使用@Bean的方法对应的类
			// 执行完这一步,当前的项目中的beanFactory的多了
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
		// 注册@ImportResource进来的Bean
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		// 注册ImportBeanDefinitionRegistrar类型的
		// 这里非常重要,AOP的实现全靠它了!!!这里会创建AnnotationAwareAspectJAutoProxyCreator
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

执行完loadBeanDefinitionsForBeanMethod(beanMethod);后,beanFactory中的BeanDefinitions增加了2个:

在这里插入图片描述

执行完loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());后,beanFactory中的BeanDefinitions增加了1个(与AOP有关的AnnotationAwareAspectJAutoProxyCreator

在这里插入图片描述
至此,我们已经将本篇中的第一个问题解决完了。 下面我们解决第二个问题

4. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

这个功能实际上是利用CGLIB来增强我们的配置类,会为Spring添加一个后置处理器:ImportAwareBeanPostProcessor

	private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
		// 实际上这里的postProcessors只有一个,即ConfigurationClassPostProcessor
		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanFactory(beanFactory);
		}
	}

我们进入ConfigurationClassPostProcessor类的postProcessBeanFactory方法

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		int factoryId = System.identityHashCode(beanFactory);
		if (this.factoriesPostProcessed.contains(factoryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
		}
		this.factoriesPostProcessed.add(factoryId);
		if (!this.registriesPostProcessed.contains(factoryId)) {
			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
			// Simply call processConfigurationClasses lazily at this point then.
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}

		// 该方法的核心方法,在4.1节下面会重点介绍
		enhanceConfigurationClasses(beanFactory);
		// 增加后置处理器
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

4.1 enhanceConfigurationClasses增强配置类

	public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
		// 拿到所有的BeanDefinition(6个内置+1个配置类+2个配置类@Bean引入的类+1个与AOP有关的类), 
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
			// configClassAttr 拿到的是配置类
			Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
			MethodMetadata methodMetadata = null;
			if (beanDef instanceof AnnotatedBeanDefinition) {
				methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
			}
			if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
				// Configuration class (full or lite) or a configuration-derived @Bean method
				// -> resolve bean class at this point...
				AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
				if (!abd.hasBeanClass()) {
					try {
						abd.resolveBeanClass(this.beanClassLoader);
					}
					catch (Throwable ex) {
						throw new IllegalStateException(
								"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
					}
				}
			}
			// 这里判断是否是full类型的Configuration.
			// full:指 @Configuration 注解的类,说明是一个完全(full)配置类
			// 若类上只有 @Component,@ComponentScan,@Import 等说明是一个简化(life)配置类
			if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
				if (!(beanDef instanceof AbstractBeanDefinition)) {
					throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
							beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
				}
				else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
					logger.info("Cannot enhance @Configuration bean definition '" + beanName +
							"' since its singleton instance has been created too early. The typical cause " +
							"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
							"return type: Consider declaring such methods as 'static'.");
				}
				// 将配置类的beanName和配置类的beanDefinition放到configBeanDefs变量中
				configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
			}
		}
		if (configBeanDefs.isEmpty()) {
			// nothing to enhance -> return immediately
			return;
		}

		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
			AbstractBeanDefinition beanDef = entry.getValue();
			// If a @Configuration class gets proxied, always proxy the target class
			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// Set enhanced subclass of the user-specified bean class
			Class<?> configClass = beanDef.getBeanClass();
			// 对配置类进行CGLIB增强
			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
			if (configClass != enhancedClass) {
				if (logger.isTraceEnabled()) {
					logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
							"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
				}
				// 把增强后的配置类放回去覆盖原来的
				// 因此,以后我们在通过Spring的上下文getBean()到的配置类都不是原始的配置类了,而是增强后的配置类
				beanDef.setBeanClass(enhancedClass);
			}
		}
	}

5. 总结

  • invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 的功能有三个
    • 【功能一】找到解析配置类的类:internalConfigurationAnnotationProcessor
    • 【功能二】利用internalConfigurationAnnotationProcessor解析配置类 ,将配置类中的@Import@ComponentScan@Bean等解析出来放入到ConfigurationClas的属性中
    • 【功能三】将ConfigurationClas的属性中对应的类转换为BeanDefinition,然后注册到beanFactiory

以上我们完成了invokeBeanFactoryPostProcessors功能的分析,下一篇我们继续分析refresh方法中的第六个方法registerBeanPostProcessors方法。

发布了397 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/xiaojie_570/article/details/104651547