Spring IOC - ConfigurationClassPostProcessor源码解析

        上文提到Spring在Bean扫描过程中,会手动将5个Processor类注册到beanDefinitionMap中,其中ConfigurationClassPostProcessor就是本文将要讲解的内容,该类会在refresh()方法中通过调用invokeBeanFactoryPosstProcessors(beanFactory)被调用。
        5个Processor类列表如下:
类名
是否BeanDefinitionRegistryPostProcessor
是否BeanFactoryPostProcessor
是否BeanPostProcessor
ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
EventListenerMethodProcessor
DefaultEventListenerFactory
        ConfigurationClassPostProcessor中两个核心方法将被调用,其主要作用如下:

方法名

作用

postProcessBeanDefinitionRegistry()

(1)@Conditional注解条件解析

(2)被以下注解标注的类及内部类

@Component、@PropertySources、@PropertySource、@ComponentScans、@ComponentScan、@Import、@ImportResource、@Bean、接口中的@Bean

postProcessBeanFactory()

对full模式的配置类BeanDefinition进行CGLib增强:把CGLib生成的子类型设置到beanDefinition中

        postProcessBeanDefinitionRegistry()源码及注释如下:


	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		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(registry)方法,其主体逻辑流程图如下:
Spring IOC - ConfigurationClassPostProcessor源码解析_第1张图片
        
        其中标红步骤为两个关键步骤:

        1. 通过beanDefinition判断是否为配置类

        Spring专门提供了一个工具类:ConfigurationClassUtils来检查是否为配置类,并标记full、lite模式,逻辑如下:

Spring IOC - ConfigurationClassPostProcessor源码解析_第2张图片
        2. 解析配置类
Spring IOC - ConfigurationClassPostProcessor源码解析_第3张图片
        doProcessConfigurationClass即为真正的对个注解的解析方法,其逻辑流程图如下:
Spring IOC - ConfigurationClassPostProcessor源码解析_第4张图片

        具体的源码及详细注释如下:

        1. 主流程processConfigBeanDefinitions方法:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		// 候选配置类定义列表
		List configCandidates = new ArrayList<>();
		// 获取容器中所有bean定义的名字
		String[] candidateNames = registry.getBeanDefinitionNames();

		for (String beanName : candidateNames) {
			// 获取bean定义
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			// org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
			// Bean Definition是否已经被标记为配置类(full、lite模式)
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			// 查看bean是否是ConfigurationClass
			//被@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean标记
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				// 是配置类,则加入到候选列表
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		// 如果为空,即找不到被@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean标记的类,则立即返回
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
		// 对需要处理的BeanDefinition排序,值越小越靠前
		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
		// 检查是否有自定义的beanName生成器
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				//获取自定义的beanName生成器
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					// 如果spring有自定义的beanName生成器,则重新赋值
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

		//如果环境对象为空,则创建新的环境对象
		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

		// 构造一个配置类解析器,用来把bean定义的重要信息提取转化为ConfigurationClass
		// Parse each @Configuration class
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		// 候选配置类定义列表(查重)
		Set candidates = new LinkedHashSet<>(configCandidates);
		// 存储已解析的配置类列表
		Set alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			// 解析配置类
			parser.parse(candidates);
			// 配置类不能被申明为final(因为CGLIB的限制),除非它声明proxyBeanMethods=false
			// 在@Configuration类中,@Bean方法的实例必须是可重写的,以适应CGLIB
			parser.validate();

			// 获取解析器中解析出的配置类ConfigurationClass: parser.getConfigurationClasses()
			Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			// 过滤掉已解析的配置类
			configClasses.removeAll(alreadyParsed);

			// 构造一个bean定义读取器
			// 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());
			}
			// 读取ConfigurationClass获取衍生bean定义并注册到容器
			// 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
			this.reader.loadBeanDefinitions(configClasses);
			// 加入已解析配置类
			alreadyParsed.addAll(configClasses);
			// 清空候选配置类定义列表
			candidates.clear();
			// 如果容器中bean定义有新增
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				// 查找出新增的配置类bean定义 start
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set 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
		// 如果想要在@Configuration类中使用ImportAware接口,需要将ImportRegistry注册为bean。这样,@Configuration类就可以
		// 使用ImportRegistry来获取导入的类信息
		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.
			// 如果MetadataReaderFactory是由外部提供的,则需要清楚其缓存。但是,如果MetadataReaderFactory是由ApplicationContext共享的,则不需要进行清除,
			// 因为ApplicationContext会自动清楚共享缓存
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

        2. 其中检查是否为配置类方法ConfigurationClassUtils.checkConfigurationClassCandidate

//检查给定的BeanDefinition是否是一个配置类的候选者(或一个在配置/组件类中声明的嵌套组件类)
	//并对其进行相应的标记处理
	//被@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean标记
	public static boolean checkConfigurationClassCandidate(
			BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

		//获取bean定义信息中的class类名
		String className = beanDef.getBeanClassName();
		//如果className为空,或者bean定义信息中的factoryMethod不等于空,那么直接返回
		if (className == null || beanDef.getFactoryMethodName() != null) {
			return false;
		}

		AnnotationMetadata metadata;
		//通过注解注入的BeanDefinition都是AnnotatedGenericBeanDefinition,实现了AnnotatedBeanDefinition
		//Spring内部的BeanDefinition都是RootBeanDefiniton,实现了AbstractBeanDefinition
		//此处主要用于判断是否是归属于AnnotatedBeanDefinition
		if (beanDef instanceof AnnotatedBeanDefinition &&
				className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
			// Can reuse the pre-parsed metadata from the given BeanDefinition...
			// 从当前bean的定义信息中获取元素
			metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
		}
		//判断是否是Spring中默认的BeanDefinition
		else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
			// Check already loaded Class if present...
			// since we possibly can't even load the class file for this Class.
			//获取当前bean对象的Class对象
			Class beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
			//如果class实例是下面4种类或者接口的子类,父接口等任何一种情况,直接返回
			if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
					BeanPostProcessor.class.isAssignableFrom(beanClass) ||
					AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
					EventListenerFactory.class.isAssignableFrom(beanClass)) {
				return false;
			}
			//为给定类创建新的AnnotationMetadata
			metadata = AnnotationMetadata.introspect(beanClass);
		}
		//如果上述两种情况都不符合
		else {
			try {
				//获取className的MetadataReader实例
				MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
				//读取底层类的完整注解元数据,包括带注解方法的元数据
				metadata = metadataReader.getAnnotationMetadata();
			}
			catch (IOException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Could not find class file for introspecting configuration annotations: " +
							className, ex);
				}
				return false;
			}
		}
		// 获取Bean Definition的元数据被@Configuration注解标注的属性字典值
		Map config = metadata.getAnnotationAttributes(Configuration.class.getName());
		// 如果bean被@Configuration注解标注,并且proxyBeanMethods属性的值为true,则标注当前配置类为full,即需要代理增强,为一个代理类
		if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
		// 如果存在,或者isConfigurationCandidate返回true,则标注当前配置类为lite,即不需要代理增强,为一个普通类
		// 标注了Configuration注解且proxyBeanMethods属性的值为false,则为lite模式
		// 没有标注Configuration注解,但是标注了Component、ComponentScan、Import、ImportResource、@Bean注解、则为lite模式
		else if (config != null || isConfigurationCandidate(metadata)) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
		}
		// 组件类不存在@Configuration注解,直接返回false
		else {
			return false;
		}

		// 获取配置类的排序顺序,设置到组件定义属性中
		// It's a full or lite configuration candidate... Let's determine the order value, if any.
		//Bean Definition是一个标记为full/lite的候选项,如果有order属性就设置order属性
		Integer order = getOrder(metadata);
		if (order != null) {
			//设置bean的order值
			beanDef.setAttribute(ORDER_ATTRIBUTE, order);
		}

		return true;
	}

        3. 真正干活的方法doProessConfigurationClass

// 通过读取源类的注释、成员和方法来构建完整的ConfigurationClass
	// 1.处理@Component
	// 2.处理每个@PropertySource
	// 3.处理每个@ComponentScan
	// 4.处理每个Impoit
	// 5.处理每个@ImportResource
	// 6.找配置类中@Bean注解的方法(找出Class中存在@Bean标注的方法,加入到ConfigurationClass的beanMethods属性)
	// 7.找接口中@Bean注解的方法
	// 8.存在父类则递归处理
	@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
			throws IOException {

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

		// Process any @PropertySource annotations
		// 处理@PropertySources和@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
		// 处理@ComponentScans和@ComponentScan注解
		Set 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 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注解
		// getImports:递归获取@Import导入的类
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

		// Process any @ImportResource annotations
		// 处理@ImportResource注解
		// 读取locations, reader属性,封装存放在importResources map集合中
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

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

		// Process default methods on interfaces
		// 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析
		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;
	}

你可能感兴趣的:(spring,java,后端)