ConfigurationClassUtils配置类检测工具详解

这个工具类在Spring的BeanDefinition扫描加载阶段具有重要作用,我们来分析一下里面的几个方法,这里的方法都是静态方法,在这里做个笔记

isFullConfigurationCandidate

这个方法很简单,就是检测当前BeanDefinition对应的class类中是否有@Configuration注解

ConfigurationClassUtils配置类检测工具详解

isFullConfigurationCandidate方法

isLiteConfigurationCandidate

判断当前BeanDefinition对应的class类上是否有@Component、@ComponentScan、@Import、@ImportResource、@Bean注解

ConfigurationClassUtils配置类检测工具详解

isLiteConfigurationCandidate方法

ConfigurationClassUtils配置类检测工具详解

candidateIndicators集合

isConfigurationCandidate

这方法是上面两个方法的或运算,判断是否是配置类

ConfigurationClassUtils配置类检测工具详解

checkConfigurationClassCandidate

这个方法出现在ConfigurationClassPostProcessor的processConfigBeanDefinitions()中,用于判断当前的BeanDefinition是否是一个配置类的候选者(或一个在配置/组件类中声明的嵌套组件类),并对其进行相应的标记处理的,如果是则返回true,不是则返回false。

ConfigurationClassUtils配置类检测工具详解

来具体分析一下这个方法:

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

		AnnotationMetadata metadata;
  	//@Component、@Bean对应的是AnnotatedBeanDefinition
		if (beanDef instanceof AnnotatedBeanDefinition &&
				className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
			// Can reuse the pre-parsed metadata from the given BeanDefinition...
      //解析出来当前BeanDefinition对应的元数据(可以理解为对应的class信息)
			metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
		}
  	//Spring内部的则是RootBeanDefinition,实现了AbstractBeanDefinition
		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.
      //获取对应的class,然后创建一个元数据类
			Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
			metadata = new StandardAnnotationMetadata(beanClass, true);
		}
		else {
			try {
        //metadataReaderFactory是一个CachingMetadataReaderFactory,继承了SimpleMetadataReaderFactory
				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;
			}
		}
		//判断类上是否有@Configuration注解,源代码在下面
		if (isFullConfigurationCandidate(metadata)) {
      //其实就是BeanDefinition中的一个map,记录一下标记
      //这里key=org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
      //value=full
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
  	//判断类上是否有@Component、@ComponentScan、@Import、@ImportResource、@Bean注解
		else if (isLiteConfigurationCandidate(metadata)) {
      //这里key=org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
			//value=lite
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
		}
		else {
      //以上几个注解没有的话,则返回false;有的话返回true
			return false;
		}

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

		return true;
	}