ConfigurationClassPostProcessor源码解读以及SpringBoot自动装配原理

文章详细介绍了Spring框架中的ConfigurationClassPostProcessor处理器,如何解析基于注解的BeanDefinition,特别是@ComponentScan、@Import、@ImportResource等注解的处理。同时,讲解了SpringBoot启动时如何通过@ComponentScan进行组件扫描,并解析配置类,实现自动装配功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ConfigurationClassPostProcessor

以注解的形式对BeanDefinition进行解析(扫描到的Beandifinition instance of ScannedGenericBeanDefinition),不再局限于xml文件的配置

由于框架层面考虑的场景很全面,很多地方都会采用递归处理操作,只要理解了一遍其他操作同理

在这里插入图片描述

当在xml配置文件中(SpringBoot启动类加入@ComponentScan效果一样)开启component-scan标签Spring会注入一个RootBeanDefinition(org.springframework.context.annotation.internalConfigurationAnnotationProcessor) -> 会指向 ConfigurationClassPostProcessor用于解析包含指定注解的BeanDefinition

<context:component-scan base-package="com.armin"></context:component-scan>

BeanDefinition

在这里插入图片描述

  • GenericBeanDefinition:从配置文件扫描获取到的BeanDefinition
    • ScannedGenericBeanDefinition
      • AnnotatedBeanDefinition:所有的能被组件component-scan扫描到的Bean(注解的类型都属于@Component)
  • RootBeanDefinition:Spring内部添加的BeanDefinition

在xml配置文件中component-scan标签在对xml文件进行解析时(obtainFreshBeanFactory)会被ComponentScanBeanDefinitionParser -> parse() 方法中进行@Component类型注解的解析,将指定路径下的class文件进行判断识别是否拥有@Componet类型的注解,并且不满足跳过该Beandifinition的条件判断,则将该Beandifinition放入BeanFactory中

判断是否需要跳过流程

  1. org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
  2. org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents
  3. org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents
  4. org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isCandidateComponent(org.springframework.core.type.classreading.MetadataReader)
  5. org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isConditionMatch
  6. org.springframework.context.annotation.ConditionEvaluator#shouldSkip(org.springframework.core.type.AnnotatedTypeMetadata)
  7. org.springframework.context.annotation.ConditionEvaluator#shouldSkip(org.springframework.core.type.AnnotatedTypeMetadata, org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase)
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
  // metadata为空或者配置类中不存在@Conditional标签
  if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
    return false;
  }

  // 采用递归的方式进行判断,第一次执行的时候phase为空,向下执行
  if (phase == null) {
    // 下面的逻辑判断中,需要进入ConfigurationClassUtils.isConfigurationCandidate方法,主要的逻辑如下:
    // 1、metadata是AnnotationMetadata类的一个实例
    // 2、检查bean中是否使用@Configuration注解
    // 3、检查bean不是一个接口
    // 4、检查bean中是否包含@Component @ComponentScan @Import @ImportResource中任意一个
    // 5、检查bean中是否有@Bean注解
    // 只要满足其中1,2或者1,3或者1,4或者1,5就会继续递归
    if (metadata instanceof AnnotationMetadata &&
        ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
      return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
    }
    return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
  }

  List<Condition> conditions = new ArrayList<>();
  for (String[] conditionClasses : getConditionClasses(metadata)) {
    for (String conditionClass : conditionClasses) {
      // 获取到@Conditional注解后面的value数组
      Condition condition = getCondition(conditionClass, this.context.getClassLoader());
      conditions.add(condition);
    }
  }
  // 对相关的条件进行排序操作
  AnnotationAwareOrderComparator.sort(conditions);

  for (Condition condition : conditions) {
    ConfigurationPhase requiredPhase = null;
    if (condition instanceof ConfigurationCondition) {
      requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
    }
    // requiredPhase只可能是空或者是ConfigurationCondition的一个实例对象
    if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {

      //此逻辑为:1.requiredPhase不是ConfigurationCondition的实例
      //2.phase==requiredPhase,从上述的递归可知:phase可为ConfigurationPhase.PARSE_CONFIGURATION或者ConfigurationPhase.REGISTER_BEAN
      //3.condition.matches(this.context, metadata)返回false
      //如果1、2或者1、3成立,则在此函数的上层将阻断bean注入Spring容器
      return true;
    }
  }

  return false;
}

postProcessBeanDefinitionRegistry()

由于实现了BeanDefinitionRegistryPostProcessor以及PriorityOrdered必将在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() -> invokeBeanDefinitionRegistryPostProcessors() 优先执行

	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		// 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过则抛出异常
		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);
		}
		// 将马上要进行处理的registry对象的id值放到已经处理的集合对象中
		this.registriesPostProcessed.add(registryId);

		// 处理配置类的bean定义信息
		processConfigBeanDefinitions(registry);
	}

processConfigBeanDefinitions()

构建和验证一个类是否被@Configuration修饰,并做相关的解析工作,如果你对此方法了解清楚了,那么springboot的自动装配原理就清楚了

	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		// 创建存放BeanDefinitionHolder的对象集合
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		// 当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的beanName
		String[] candidateNames = registry.getBeanDefinitionNames();

		// 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的)
		for (String beanName : candidateNames) {
			// 获取指定名称的BeanDefinition对象
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			// 如果beanDefinition中的configurationClass属性不等于空,那么意味着已经处理过,输出日志信息
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			// 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用
			// 如果Configuration配置proxyBeanMethods代理为true则为full
			// 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite
			// 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值
			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
		// 判断当前类型是否是SingletonBeanRegistry类型
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			// 类型的强制转换
			sbr = (SingletonBeanRegistry) registry;
			// 判断是否有自定义的beanName生成器
			if (!this.localBeanNameGeneratorSet) {
				// 获取自定义的beanName生成器
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				// 如果有自定义的命名生成策略
 				if (generator != null) {
					//设置组件扫描的beanName生成策略
					this.componentScanBeanNameGenerator = generator;
					// 设置import bean name生成策略
					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);

		// 创建两个集合对象,
		// 存放相关的BeanDefinitionHolder对象
		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		// 存放扫描包下的所有bean
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			// 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition
			parser.parse(candidates);
			// 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB
			parser.validate();

			// 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象
			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			// 清除掉已经解析处理过的配置类
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			// 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			// 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
			this.reader.loadBeanDefinitions(configClasses);
			// 添加到已经处理的集合中
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			// 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition
			// 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean)
			// 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length
			// 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析
			// 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了
			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());
				}
				// 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中
				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();
		}
	}
checkConfigurationClassCandidate()

检查当前给定的beanDefinition中是否是一个配置类的候选者,判断在嵌套的关系中是否包含配置类或者组件类或者自动注册进去的,并做相应的标记

	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;
		// 通过注解注入的db都是AnnotatedGenericBeanDefinition,实现了AnnotatedBeanDefinition
		// spring内部的bd是RootBeanDefinition,实现了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实例是下面四种类或接口的子类、父接口等任何一种情况,直接返回
			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定义的元数据被@Configuration注解标注的属性字典值
		Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
		// 如果bean被@Configuration注解标注,且属性proxyBeanMethods为false(使用代理模式),则将bean定义记为full
		if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
		// 如果bean被@configuration注解标注,且被注解@Component,@ComponentScan、@Import、@ImportResource或者@Bean标记的方法,则将bean定义标记为lite
		else if (config != null || isConfigurationCandidate(metadata)) {
			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.
		// bean定义是一个标记为full或lite的候选项,如果设置order则设置order属性值
		Integer order = getOrder(metadata);
		// 如果值不为空的话,那么直接设置值到具体的beanDefinition
		if (order != null) {
			// 设置bean定义的order值
			beanDef.setAttribute(ORDER_ATTRIBUTE, order);
		}

		return true;
	}
isConfigurationCandidate()

检查给定的元数据,以查找给定的候选配置类是否被指定的注解标注

	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?
		// 检查是否被注解@Component、@ComponentScan、@Import、@ImportResource标注
		for (String indicator : candidateIndicators) {
			if (metadata.isAnnotated(indicator)) {
				return true;
			}
		}

		// Finally, let's look for @Bean methods...
		// 最后检查是否有@Bean标注的方法
		try {
			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;
		}
	}
自定义BeanName

如果需要自定义bean的名称则需要实现BeanNameGenerator

parse()

解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition

if判断条件于同上checkConfigurationClassCandidate()一一对应

	public void parse(Set<BeanDefinitionHolder> configCandidates) {
		// 循环遍历configCandidates
		for (BeanDefinitionHolder holder : configCandidates) {
			// 获取BeanDefinition
			BeanDefinition bd = holder.getBeanDefinition();
			// 根据BeanDefinition类型的不同,调用parse不同的重载方法,实际上最终都是调用processConfigurationClass()方法
			try {
				// 注解类型
				if (bd instanceof AnnotatedBeanDefinition) {
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				// 有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);
			}
		}

		// 执行找到的DeferredImportSelector
		// DeferredImportSelector是ImportSelector的一个子类
		// ImportSelector被设计成和@Import注解同样的效果,但是实现了ImportSelector的类可以条件性的决定导入某些配置
		// DeferredImportSelector的设计魔都是在所有其他的配置类被处理后才进行处理
		this.deferredImportSelectorHandler.process();
	}

这里的parse()对应如下parse()

	// 根据className和beanName解析配置文件,读取元数据
	protected final void parse(@Nullable String className, String beanName) throws IOException {
		Assert.notNull(className, "No bean class name for configuration class bean definition");
		MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
		processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
	}

	// 根据Class和beanName解析配置文件,有Class对象
	protected final void parse(Class<?> clazz, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
	}

	// 根据注解元数据和beanName解析配置文件,有注解元数据
	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
	}

最终都将执行processConfigurationClass()

此处的shouldSkip()同上

	protected void  processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
		// 判断是否跳过解析
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}

		// 第一次进入的时候,configurationClass的size为0,existingClass肯定为null,在此处处理configuration重复import
		// 如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回,如果配置类不是被导入的,则移除旧的使用新的配置类
		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					// 如果要处理的配置类configclass在已经分析处理的配置类记录中已存在,合并两者的importBy属性
					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.

		// 处理配置类,由于配置类可能存在父类(若父类的全类名是以java开头的,则除外),所有需要将configClass变成sourceClass去解析,然后返回sourceClass的父类。
		// 如果此时父类为空,则不会进行while循环去解析,如果父类不为空,则会循环的去解析父类
		// SourceClass的意义:简单的包装类,目的是为了以统一的方式去处理带有注解的类,不管这些类是如何加载的
		// 如果无法理解,可以把它当做一个黑盒,不会影响看spring源码的主流程
		SourceClass sourceClass = asSourceClass(configClass, filter);
		do {
			// 解析各种注解
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		while (sourceClass != null);

		// 将解析的配置类存储起来,这样回到parse方法时,能取到值
		this.configurationClasses.put(configClass, configClass);
	}
doProcessConfigurationClass()

通过从源类读取注释、成员和方法,应用处理并构建一个完整的ConfigurationClass。当发现相关源时,可以多次调用此方法

主要处理如下注解

  1. @Component
  2. @PropertySources
  3. @ComponentScans |@ComponentScan
  4. @Import
  5. @ImportResource
  6. @Bean
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
		// @Configuration继承了@Component
		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// Recursively process any member (nested) classes first
			// 递归处理内部类,因为内部类也是一个配置类,配置类上有@configuration注解,该注解继承@Component,if判断为true,调用processMemberClasses方法,递归解析配置类中的内部类
			processMemberClasses(configClass, sourceClass, filter);
		}

		// Process any @PropertySource annotations
		// 如果配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中
		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
		// 处理@ComponentScan或者@ComponentScans注解,并将扫描包下的所有bean转换成填充后的ConfigurationClass
		// 此处就是将自定义的bean加载到IOC容器,因为扫描到的类可能也添加了@ComponentScan和@ComponentScans注解,因此需要进行递归解析
		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
				// 解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类
				// 比如 basePackages = com.mashibing, 那么在这一步会扫描出这个包及子包下的class,然后将其解析成BeanDefinition
				// (BeanDefinition可以理解为等价于BeanDefinitionHolder)
				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
				// 通过上一步扫描包com.mashibing,有可能扫描出来的bean中可能也添加了ComponentScan或者ComponentScans注解.
				//所以这里需要循环遍历一次,进行递归(parse),继续解析,直到解析出的类上没有ComponentScan和ComponentScans
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					// 判断是否是一个配置类,并设置full或lite属性
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						// 通过递归方法进行解析
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// Process any @Import annotations
		// 处理@Import注解
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

		// Process any @ImportResource annotations
		// 处理@ImportResource注解,导入spring的配置文件
		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
		// 处理加了@Bean注解的方法,将@Bean方法转化为BeanMethod对象,保存再集合中
		Set<MethodMetadata> 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;
	}
processMemberClasses()

递归处理内部类,因为内部类也是一个配置类,配置类上有@configuration注解,该注解继承@Component,if判断为true,调用processMemberClasses方法,递归解析配置类中的内部类

	private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
			Predicate<String> filter) throws IOException {

		// 找到内部类,内部类中也可能是一个配置类
		Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
		// 如果不等于空的话
		if (!memberClasses.isEmpty()) {
			List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
			// 循环判断内部类是不是配置类
			for (SourceClass memberClass : memberClasses) {
				if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
						!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
					candidates.add(memberClass);
				}
			}
			// 对配置类进行排序操作
			OrderComparator.sort(candidates);
			// 遍历符合规则的类
			for (SourceClass candidate : candidates) {
				if (this.importStack.contains(configClass)) {
					// 出现配置类循环导入,则直接报错
					this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
				}
				else {
					// 将配置类入栈
					this.importStack.push(configClass);
					try {
						// 调用processConfigurationClass方法,因为内部类中还可能包含内部类,所以需要在做循环解析,实际工作中是不会有这中情况的
						processConfigurationClass(candidate.asConfigClass(configClass), filter);
					}
					finally {
						// 解析完出栈
						this.importStack.pop();
					}
				}
			}
		}
	}
  • isConfigurationCandidate()同上
  • processConfigurationClass()同上
processPropertySource()

处理给定的使用@PropertySource注解修饰的类

	private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
		// 获取name属性
		String name = propertySource.getString("name");
		if (!StringUtils.hasLength(name)) {
			name = null;
		}
		// 获取encoding属性
		String encoding = propertySource.getString("encoding");
		if (!StringUtils.hasLength(encoding)) {
			encoding = null;
		}
		// 获取value属性
		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 {
				// 处理属性值的占位符
				String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
				// 讲指定位置的资源转换成resource对象
				Resource resource = this.resourceLoader.getResource(resolvedLocation);
				// 添加resource对象为属性资源
				addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
			}
			catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException 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;
				}
			}
		}
	}
@ComponetScan注解的解析

ComponentScanAnnotationParser -> parse()

解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类,从而获取到包下包含的BeanDefinitionHolder信息

	public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
		// 创建对应的扫描类
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
				componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

		// 获取@ComponentScan的参数,并进行参数的设置工作
		Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
		boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
		scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
				BeanUtils.instantiateClass(generatorClass));

		// 获取scopedProxy属性
		ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
		if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
			scanner.setScopedProxyMode(scopedProxyMode);
		}
		else {
			Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
			scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
		}

		// 获取resourcePattern属性
		scanner.setResourcePattern(componentScan.getString("resourcePattern"));

		// 获取includeFilters属性
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addIncludeFilter(typeFilter);
			}
		}
		// 获取excludeFilters属性
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addExcludeFilter(typeFilter);
			}
		}

		// 获取lazyInit属性
		boolean lazyInit = componentScan.getBoolean("lazyInit");
		if (lazyInit) {
			scanner.getBeanDefinitionDefaults().setLazyInit(true);
		}

		Set<String> basePackages = new LinkedHashSet<>();
		// 获取basePackages属性
		String[] basePackagesArray = componentScan.getStringArray("basePackages");
		for (String pkg : basePackagesArray) {
			String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
			Collections.addAll(basePackages, tokenized);
		}
		// 获取basePackageClasses属性
		for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
			basePackages.add(ClassUtils.getPackageName(clazz));
		}
		if (basePackages.isEmpty()) {
			basePackages.add(ClassUtils.getPackageName(declaringClass));
		}

		scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
			@Override
			protected boolean matchClassName(String className) {
				return declaringClass.equals(className);
			}
		});
		// 开始执行扫描,最终的扫描器是ClassPathBeanDefinitionScanner
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}

doScan()

执行扫描,获取BeanDefinitionHolder

	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		// 遍历basePackages
		for (String basePackage : basePackages) {
			// 扫描basePackage,将符合要求的bean定义全部找出来
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			// 遍历所有候选的bean定义
			for (BeanDefinition candidate : candidates) {
				// 解析@Scope注解,包括scopeName和proxyMode
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				// 使用beanName生成器来生成beanName
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					// 处理beanDefinition对象,例如,此bean是否可以自动装配到其他bean中
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					// 处理定义在目标类上的通用注解,包括@Lazy,@Primary,@DependsOn,@Role,@Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 检查beanName是否已经注册过,如果注册过,检查是否兼容
				if (checkCandidate(beanName, candidate)) {
					// 将当前遍历bean的bean定义和beanName封装成BeanDefinitionHolder
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					// 根据proxyMode的值,选择是否创建作用域代理
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					// 注册beanDefinition
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}
处理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

@Import主要加载制定的配置类

getImports(sourceClass)

获取当前解析类中所有的所有含@Import注解导入的配置类

	private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
		// 创建集合,存储包含@Import注解的类
		Set<SourceClass> imports = new LinkedHashSet<>();
		// 创建集合,为了实现递归调用
		Set<SourceClass> visited = new LinkedHashSet<>();
		// 收集@Import注解的类
		collectImports(sourceClass, imports, visited);
		return imports;
	}

collectImports()

递归处理其他可能包含@Import的注解类

private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
      throws IOException {

   if (visited.add(sourceClass)) {
      for (SourceClass annotation : sourceClass.getAnnotations()) {
         String annName = annotation.getMetadata().getClassName();
         // 递归处理其他可能包含@Import的注解类
         if (!annName.equals(Import.class.getName())) {
            collectImports(annotation, imports, visited);
         }
      }
      // 获取Import注解的值
      imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
   }
}

processImports()

实例化@Import导入的配置类并处理

	private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {

		// 如果使用@Import注解修饰的类集合为空,那么直接返回
		if (importCandidates.isEmpty()) {
			return;
		}
		// 通过一个栈结构解决循环引入
		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			// 添加到栈中,用于处理循环引入的问题
			this.importStack.push(configClass);
			try {
				// 遍历每一个@Import注解的类
				for (SourceClass candidate : importCandidates) {
					// 检验配置类Import引入的类是否是ImportSelector子类
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						// 候选类是一个导入选择器->委托来确定是否进行导入
						Class<?> candidateClass = candidate.loadClass();
						// 通过反射生成一个ImportSelect对象
						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);
						}
						// 判断引用选择器是否是DeferredImportSelector接口的实例
						// 如果是则应用选择器将会在所有的配置类都加载完毕后加载
						if (selector instanceof DeferredImportSelector) {
							// 将选择器添加到deferredImportSelectorHandler实例中,预留到所有的配置类加载完成后统一处理自动化配置类
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
							// 获取引入的类,然后使用递归方式将这些类中同样添加了@Import注解引用的类
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
							// 递归处理,被Import进来的类也有可能@Import注解
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
					// 如果是实现了ImportBeanDefinitionRegistrar接口的bd
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						// 候选类是ImportBeanDefinitionRegistrar  -> 委托给当前注册器注册其他bean
 						Class<?> candidateClass = candidate.loadClass();
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
						/**
						 * 放到当前configClass的importBeanDefinitionRegistrars中
						 * 在ConfigurationClassPostProcessor处理configClass时会随之一起处理
						 */
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						// 候选类既不是ImportSelector也不是ImportBeanDefinitionRegistrar-->将其作为@Configuration配置类处理
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
						/**
						 * 如果Import的类型是普通类,则将其当作带有@Configuration的类一样处理
						 * 将candidate构造为ConfigurationClass,标注为importedBy,意味着它是通过被@Import进来的
						 * 后面处理会用到这个判断将这个普通类注册进DefaultListableBeanFactory
						 */
						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();
			}
		}
	}
// 将选择器添加到deferredImportSelectorHandler实例中,预留到所有的配置类加载完成后统一处理自动化配置类
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
  DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
  if (this.deferredImportSelectors == null) {
    DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
    handler.register(holder);
    handler.processGroupImports();
  }
  else {
    this.deferredImportSelectors.add(holder);
  }
}

最终会在外层解析完毕后org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)中作处理

	public void parse(Set<BeanDefinitionHolder> configCandidates) {
 	......

		// 执行找到的DeferredImportSelector
		// DeferredImportSelector是ImportSelector的一个子类
		// ImportSelector被设计成和@Import注解同样的效果,但是实现了ImportSelector的类可以条件性的决定导入某些配置
		// DeferredImportSelector的设计魔都是在所有其他的配置类被处理后才进行处理
		this.deferredImportSelectorHandler.process();
	}
public void process() {
  // 此处获取@Import注解导入器
  List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
  this.deferredImportSelectors = null;
  try {
    if (deferredImports != null) {
      DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
      deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
      deferredImports.forEach(handler::register);
      // 核心处理类,此处完成自动配置功能
      handler.processGroupImports();
    }
  }
  finally {
    this.deferredImportSelectors = new ArrayList<>();
  }
}

具体的处理逻辑,最终还是会调processImports()进行处理

public void processGroupImports() {
  for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
    Predicate<String> exclusionFilter = grouping.getCandidateFilter();
    // getImports方法是读取自动化配置类的核心入口,
    grouping.getImports().forEach(entry -> {
      ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
      try {
        // 配置类中可能会包含@Import注解引入的类,通过此方法将引入的类注入
        processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
                       Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
                       exclusionFilter, false);
      }
      catch (BeanDefinitionStoreException ex) {
        throw ex;
      }
      catch (Throwable ex) {
        throw new BeanDefinitionStoreException(
          "Failed to process import candidates for configuration class [" +
          configurationClass.getMetadata().getClassName() + "]", ex);
      }
    });
  }
}

扩展

SpringBoot自动装配

springboot的自动装配也是在@Import标签处理实现的,具体实现流程如下:

springbeanFactoryPostProcessor处理方法时invokeBeanFactoryPostProcessors(beanFactory)实现了BeanFactoryPostProcessor接口的核心处理类ConfigurationClassPostProcessor,这个类主要用来解析相关注解(@Component,@PropertySources,@ComponentScan,@Import,@ImportResource,@Bean)的解析工作,当解析@Import时从启动类挨个查找能识别到AutoConfigurationImportSelector这个类,在这个类进行解析的时候,有个延迟加载deferredImportSelectorHandler的属性会通过processImports(configClass, sourceClass, getImports(sourceClass), filter, true)方法里的子过程processGroupImports()处理,(grouping.getImports().forEach(entry…如上代码所示)中的getImports作为configurationClasses的entry,最后显示调用了getCandidateConfigurations方法找到EnableAutoConfiguration.class这个entry,这时就能把配置文件对应属性值都加载回来,完成自动装配环节。

public Iterable<Group.Entry> getImports() {
  for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
     // 核心方法,在springboot中此方法会去SpringFactoriesLoader类中加载自动化配置类
     this.group.process(deferredImport.getConfigurationClass().getMetadata(),
           deferredImport.getImportSelector());
  }
  // 获取已经取得的配置类
  return this.group.selectImports();
}

springboot中找到org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process这是Group接口process()方法AutoConfigurationImportSelector的实现

public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
 Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector, () -> {
   return String.format("Only %s implementations are supported, got %s", AutoConfigurationImportSelector.class.getSimpleName(), deferredImportSelector.getClass().getName());
 });
 AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector)deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);
 this.autoConfigurationEntries.add(autoConfigurationEntry);
 Iterator var4 = autoConfigurationEntry.getConfigurations().iterator();

 while(var4.hasNext()) {
   String importClassName = (String)var4.next();
   this.entries.putIfAbsent(importClassName, annotationMetadata);
 }

}

getAutoConfigurationEntry()获取配置中

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
 if (!this.isEnabled(annotationMetadata)) {
   return EMPTY_ENTRY;
 } else {
   AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
   List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
   configurations = this.removeDuplicates(configurations);
   //排除不需要的加载
   Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
   this.checkExcludedClasses(configurations, exclusions);
   configurations.removeAll(exclusions);
   configurations = this.getConfigurationClassFilter().filter(configurations);
   this.fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
 }
}

getCandidateConfigurations()获取配置文件中的指定的键值对

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
 Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
 return configurations;
}

getSpringFactoriesLoaderFactoryClass()获取key -> EnableAutoConfiguration

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
 return EnableAutoConfiguration.class;
}

loadFactoryNames()获取values

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
 ClassLoader classLoaderToUse = classLoader;
 if (classLoader == null) {
   classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
 }

 String factoryTypeName = factoryType.getName();
 return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

loadSpringFactories()具体的解析配置文件操作

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
 Map<String, List<String>> result = (Map)cache.get(classLoader);
 if (result != null) {
   return result;
 } else {
   HashMap result = new HashMap();

   try {
     //获取配置文件的路径
     Enumeration urls = classLoader.getResources("META-INF/spring.factories");

     while(urls.hasMoreElements()) {
       URL url = (URL)urls.nextElement();
       UrlResource resource = new UrlResource(url);
       Properties properties = PropertiesLoaderUtils.loadProperties(resource);
       Iterator var6 = properties.entrySet().iterator();

       while(var6.hasNext()) {
         Entry<?, ?> entry = (Entry)var6.next();
         String factoryTypeName = ((String)entry.getKey()).trim();
         String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
         String[] var10 = factoryImplementationNames;
         int var11 = factoryImplementationNames.length;

         for(int var12 = 0; var12 < var11; ++var12) {
           String factoryImplementationName = var10[var12];
           ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
             return new ArrayList();
           })).add(factoryImplementationName.trim());
         }
       }
     }

     result.replaceAll((factoryType, implementations) -> {
       return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
     });
     cache.put(classLoader, result);
     return result;
   } catch (IOException var14) {
     throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
   }
 }
}

如何扩展实现自动装配

首先在resource资源文件夹下创建META-INF文件夹,以及在该文件夹中创建spring.factories文件,该文件为properties类型文件只需要key = EnableAutoConfigurationvalue指定为你自己要自动转配的class文件,均为全限定名

当然如果要实现自动装配到容器中,@Component类型是必不可少的,其解析到这些BeanDefinition对象后处理逻辑与ConfigurationClassPostProcessor处理一致

SpringBoot配置文件的解析主要为该接口的实现

org.springframework.boot.env.PropertySourceLoader:SpringBoot主要有两种实现方式

  1. PropertiesPropertySourceLoader -> *.properties
  2. YamlPropertySourceLoader -> *.yml/*.yaml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值