ConfigurationClassPostProcessor源码分析

ConfigurationClassParser/ConfigurationClassBeanDefinitionReader/ConfigurationClassEnhancer

Posted by Jay on August 2, 2019

ConfigurationClassPostProcessor源码分析

ConfigurationClassPostProcessor的类继承图如下:

可见ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor和PriorityOrdered这三个接口。

ConfigurationClassPostProcessor是在Spring应用上下文启动的时候注册到应用上下文的。当在xml配置文件中配置了<context:annotation-config/><context:component-scan/>元素,于是在解析xml文件的时候就会向BeanFactory注册ConfigurationClassPostProcessor BeanDefinition。此外,使用AnnotationConfigApplicationContext时,其内部使用的AnnotatedBeanDefinitionReader初始化时也会注册ConfigurationClassPostProcessor BeanDefinition。以上几种情况,注册ConfigurationClassPostProcessor时,最终调用的方法是AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)。

由于ConfigurationClassPostProcessor是BeanFactoryPostProcessor实现,因此该后置处理器的回调方法会在BeanDefinition加载、注册到BeanFactory之后调用,主要用于处理@Configuration配置类。例如下面的配置类:

@Configuration
@PropertySource("classpath:props.properties") // 导入属性源
@ComponentScan(basePackages = {"configuration.annotation"}) // 测试组件扫描
@Import(TeacherImportSelector.class) // 导入ImportSelector实现
public class ClassA extends ClassB implements ClassC { // 配置类 继承超类、实现接口
	
   // 内部类
   @Import(ImportBeanDefinitionRegistrarTest.class) // 导入ImportBeanDefinitionRegistrar实现
   public class ClassE extends ClassF {

      @Bean
      public Date date() { // @Bean方法
         return new Date();
      }

   }

   @Bean
   public Student student() {
      return new Student();
   }

   @Bean
   public String aa() {
      student();
      return "aa";
   }

}
// 配置类
@Configuration
class ClassB {

   @Bean
   public String helloWorld() {
      return "hello, world";
   }

}
// 测试 接口@Bean方法
interface ClassC {

   @Bean
   default int defaultMethod() {
      return 0;
   }

}
// 测试 类@Bean方法
class ClassF {

   @Bean
   public String sayHi() {
      return "hi";
   }

}
// 测试ImportSelector实现
class TeacherImportSelector implements ImportSelector {
   @Override
   public String[] selectImports(AnnotationMetadata importingClassMetadata) {
      return new String[]{Teacher.class.getName(), Student.class.getName()};
   }
}
// 测试ImportBeanDefinitionRegistrar实现
class ImportBeanDefinitionRegistrarTest implements ImportBeanDefinitionRegistrar {
   @Override
   public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      RootBeanDefinition beanDefinition = new RootBeanDefinition(Driver.class);
      BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
   }
}

引导类:

public class AllConfigTest {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
			// 配置类注册
      context.register(ClassA.class);
			// 刷新容器
      context.refresh();
			// 获取Bean实例
      context.getBean("date");
      context.getBean("helloWorld");
      context.getBean("sayHi");
      context.getBean(Driver.class);
      System.out.println(context.getBean("user"));
      context.getBean("student"); 
      context.getBean("configuration.annotation.Teacher");
   }
}

对于以上的配置类,当它注册到BeanFactory时会被ConfigurationClassPostProcessor处理。下面开始详细分析ConfigurationClassPostProcessor的处理逻辑。

一、配置类处理入口postProcessBeanDefinitionRegistry

// 根据配置类的内容,注册BeanDefinitions到BeanRegistry
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); // 处理入口
}

配置类的处理入口在postProcessBeanDefinitionRegistry方法,具体在processConfigBeanDefinitions方法。

// 根据已注册到BeanFactory的@Configuration配置类BeanDefinition,构建配置类模型集合,并根据配置类模型
// 注册BeanDefinition,如@Bean注解方法、@ImportResource注解处理等。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
   String[] candidateNames = registry.getBeanDefinitionNames(); // 取出容器中已经存在的所有bean定义的名字

   for (String beanName : candidateNames) {
      BeanDefinition beanDef = registry.getBeanDefinition(beanName);
      // 判断是否已经处理过
      if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
            ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
         if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
         }
      }
      // 判断每个bean定义是否是配置类(被@Configuration,@Component,@ComponentScan,@Import,
      // @ImportResource标记的),如果是则会给这个bean definition增加一个属性,避免重复解析
      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 排序
   configCandidates.sort((bd1, bd2) -> {
      int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); // 获取order,默认LOWEST_PRECEDENCE
      int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
      return Integer.compare(i1, i2);
   });

   // Detect any custom bean name generation strategy supplied through the enclosing application context
   // 设置自定义的BeanNameGenerator
   SingletonBeanRegistry sbr = null;
   if (registry instanceof SingletonBeanRegistry) {
      sbr = (SingletonBeanRegistry) registry;
      if (!this.localBeanNameGeneratorSet) {
         BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
         if (generator != null) {
            this.componentScanBeanNameGenerator = generator;
            this.importBeanNameGenerator = generator;
         }
      }
   }

   if (this.environment == null) { // 设置环境
      this.environment = new StandardEnvironment();
   }

   // Parse each @Configuration class 解析每个@Configuration注解的类,
   // 用于将@Configuration注解的类转换成ConfigurationClass,供ConfigurationClassBeanDefinitionReader注册BeanDefinition。
   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 {
      parser.parse(candidates); // 配置类解析入口
      parser.validate(); // 校验

      // 得到配置类模型集合
      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());
      }
      this.reader.loadBeanDefinitions(configClasses); // 根据configClasses加载BeanDefinitions并注册
      alreadyParsed.addAll(configClasses); // configClasses添加到已处理的集合

      candidates.clear();
      if (registry.getBeanDefinitionCount() > candidateNames.length) { // 有新的BeanDefinition新增
         String[] newCandidateNames = registry.getBeanDefinitionNames(); // 新的bean names集合
         Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); // 旧的bean names集合
         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()); // 注册ImportStack
   }

   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(); // 清理缓存
   }
}

上面processConfigBeanDefinitions方法中判断BeanFactory中的BeanDefinition是否是配置类的逻辑如下:

ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)
// 判断指定的BeanDefinition是否是配置类
public static boolean checkConfigurationClassCandidate(
      BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

   String className = beanDef.getBeanClassName();
   if (className == null || beanDef.getFactoryMethodName() != null) {
      return false;
   }

   AnnotationMetadata metadata;
   if (beanDef instanceof AnnotatedBeanDefinition &&
         className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
      // Can reuse the pre-parsed metadata from the given BeanDefinition... AnnotationMetadata已解析
      metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
   }
   else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
      // Check already loaded Class if present... 如果类已加载,使用StandardAnnotationMetadata
      // since we possibly can't even load the class file for this Class.
      Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
      metadata = new StandardAnnotationMetadata(beanClass, true);
   }
   else {
      try {
         MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
         metadata = metadataReader.getAnnotationMetadata(); // ASM实现
      }
      catch (IOException ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("Could not find class file for introspecting configuration annotations: " +
                  className, ex);
         }
         return false;
      }
   }

   if (isFullConfigurationCandidate(metadata)) { // 是否完全模式,注解@Configuration
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
   }
   else if (isLiteConfigurationCandidate(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.
   Integer order = getOrder(metadata); // 获取order
   if (order != null) {
      beanDef.setAttribute(ORDER_ATTRIBUTE, order); // 设置order属性
   }

   return true;
}

可见配置类分为完全模式和轻量模式两种:

  • 判断是否是完全模式的配置类(CGLIB增强)

    public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
       return metadata.isAnnotated(Configuration.class.getName());
    }
    

    类上注解了@Configuration注解的类就是完全模式的配置类。

  • 判断是否是轻量模式的配置类(无CGLIB增强)

    public static boolean isLiteConfigurationCandidate(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;
       }
    }
    

    可见配置类注解了@Component、 @ComponentScan 、@Import、@ImportResource或者存在@Bean注解的方法,则是轻量模式的配置类。

然后走到下面这句代码:

parser.parse(candidates); // 解析入口

到这里将会由ConfigurationClassParser这个类执行真正的配置类解析动作。

// ConfigurationClassParser类
public void parse(Set<BeanDefinitionHolder> configCandidates) {
   for (BeanDefinitionHolder holder : configCandidates) { // 遍历每个BeanDefinition并解析
      BeanDefinition bd = holder.getBeanDefinition(); // 获取BeanDefinition
      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(); // 处理DeferredImportSelector
}

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); // ASM
	processConfigurationClass(new ConfigurationClass(reader, beanName));
}

protected final void parse(Class<?> clazz, String beanName) throws IOException {
	processConfigurationClass(new ConfigurationClass(clazz, beanName));
}

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

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
	// 根据@Conditional注解,判断是否跳过处理
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
		return;
	}

	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); // 获取SourceClass
	do {
		sourceClass = doProcessConfigurationClass(configClass, sourceClass); // sourceClass可能是configClass本身或其超类
	}
	while (sourceClass != null);

	this.configurationClasses.put(configClass, configClass);
}

ConfigurationClassParser.doProcessConfigurationClass方法会对配置类及其父类、父接口、内部类上的@Component、@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean方法等进行处理。下面按照顺序依次分析这些内容。

// ConfigurationClassParser
// 构建一个完整的ConfigurationClass模型,不断读取找到的SourceClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {
	 // 处理注解@Component
   if (configClass.getMetadata().isAnnotated(Component.class.getName())) { 
      // Recursively process any member (nested) classes first 先递归处理任何成员内部(嵌套)类
      processMemberClasses(configClass, sourceClass);
   }

   // Process any @PropertySource annotations 处理配置类上的@PropertySource
   // 获取所有@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 处理配置类上的@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 扫描BeanDefinition
         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();
            }
            // 判断指定的BeanDefinition是否是配置类,如果是,则递归解析扫描出来的该BeanDefinition
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
               parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
         }
      }
   }

   // Process any @Import annotations 处理配置类上的@Import注解
   processImports(configClass, sourceClass, getImports(sourceClass), true);

   // Process any @ImportResource annotations 处理配置类上的@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,记录资源与BeanDefinitionReader的对应关系
         configClass.addImportedResource(resolvedResource, readerClass);
      }
   }

   // Process individual @Bean methods 处理配置类中的@Bean注解方法
   Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
   for (MethodMetadata methodMetadata : beanMethods) {
      // 记录BeanMethod到configClass
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
   }

   // Process default methods on interfaces 处理sourceClass配置类实现的接口上的默认方法
   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;
}

二、配置类@Component注解处理

// doProcessConfigurationClass方法局部
if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // 处理注解@Component
   // Recursively process any member (nested) classes first 先递归处理任何成员内部(嵌套)类
   processMemberClasses(configClass, sourceClass);
}

对于注解了@Component的配置类,先递归处理其成员内部(嵌套)类。

// Register member (nested) classes that happen to be configuration classes themselves.
// 处理configClass的内部配置类
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
   // 获取sourceClass的内部成员类或者接口(不包含继承的)
   Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
   if (!memberClasses.isEmpty()) {
      List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
      for (SourceClass memberClass : memberClasses) {
         // 如果memberClass是配置类(Full/Lite),且memberClass类名与configClass不相等,则添加到候选列表
         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 {
               // 将SourceClass转换为ConfigurationClass继续处理
               processConfigurationClass(candidate.asConfigClass(configClass));
            }
            finally {
               this.importStack.pop();
            }
         }
      }
   }
}

对于成员内部配置类,处理逻辑是递归调用processConfigurationClass方法,进行内部配置类的解析,比如例子中的ClassE

三、配置类@PropertySources注解处理

// doProcessConfigurationClass方法局部
// Process any @PropertySource annotations 处理配置类上的@PropertySource
// 获取所有@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");
   }
}

首先获取所有@PropertySource注解的属性AnnotationAttributes数组,然后根据AnnotationAttributes依次处理每个@PropertySource注解。

// 处理@PropertySource注解
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
   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");

   // PropertySource工厂
   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 = this.resourceLoader.getResource(resolvedLocation); // 获取资源
         // 创建并添加PropertySource
         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;
         }
      }
   }
}

// 添加属性源
private void addPropertySource(PropertySource<?> propertySource) {
   String name = propertySource.getName();
   MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();

   if (this.propertySourceNames.contains(name)) { // 已存在对应名称的属性源
      // We've already added a version, we need to extend it
      PropertySource<?> existing = propertySources.get(name);
      if (existing != null) {
         PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ?
               ((ResourcePropertySource) propertySource).withResourceName() : propertySource);
         if (existing instanceof CompositePropertySource) { // 如果是合成的属性源
            ((CompositePropertySource) existing).addFirstPropertySource(newSource); // propertySource放到第一位
         }
         else {
            if (existing instanceof ResourcePropertySource) {
               existing = ((ResourcePropertySource) existing).withResourceName();
            }
            CompositePropertySource composite = new CompositePropertySource(name);
            composite.addPropertySource(newSource);
            composite.addPropertySource(existing);
            propertySources.replace(name, composite); // 替换已存在的属性源
         }
         return;
      }
   }

   if (this.propertySourceNames.isEmpty()) {
      propertySources.addLast(propertySource);
   }
   else {
      // 第一个处理的属性源
      String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
      propertySources.addBefore(firstProcessed, propertySource); // propertySource放在最前面
   }
   this.propertySourceNames.add(name);
}

四、配置类@ComponentScan注解处理

// doProcessConfigurationClass方法局部
// Process any @ComponentScan annotations 处理配置类上的@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 扫描BeanDefinition
      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();
         }
         // 判断指定的BeanDefinition是否是配置类,如果是,则递归解析扫描出来的该BeanDefinition
         if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
            parse(bdCand.getBeanClassName(), holder.getBeanName());
         }
      }
   }
}

对于@ComponentScan注解,首先依次获取这些注解的AnnotationAttributes集合,然后针对每个@ComponentScan注解,使用ComponentScanAnnotationParser进行BeanDefinition扫描与注册。然后判断得到的每个BeanDefinition是否是配置类,如果是,则递归解析这些配置类。

五、配置类@Import注解处理

// doProcessConfigurationClass方法局部
// Process any @Import annotations 处理配置类上的@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), true);

首先调用getImports(sourceClass)方法获取导入类:

// 获取所有由@Import注解导入的类,考虑元注解
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
   Set<SourceClass> imports = new LinkedHashSet<>();
   Set<SourceClass> visited = new LinkedHashSet<>();
   collectImports(sourceClass, imports, visited); // 收集
   return imports;
}

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

   if (visited.add(sourceClass)) {
      // 获取所有注解对应的SourceClass并遍历
      for (SourceClass annotation : sourceClass.getAnnotations()) {
         String annName = annotation.getMetadata().getClassName(); // 注解类名
         if (!annName.startsWith("java") && !annName.equals(Import.class.getName())) { // 排除@Import注解
            collectImports(annotation, imports, visited);
         }
      }
      // 添加导入类
      imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
   }
}

然后调用processImports方法处理这些导入类:

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

   if (importCandidates.isEmpty()) { // 为空,直接返回
      return;
   }
   // 判断configClass是否构成链式导入
   if (checkForCircularImports && isChainedImportOnStack(configClass)) {
      this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
   }
   else {
      this.importStack.push(configClass);
      try {
         for (SourceClass candidate : importCandidates) {
            if (candidate.isAssignable(ImportSelector.class)) { // ImportSelector实现类直接处理
               Class<?> candidateClass = candidate.loadClass();
               ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
               ParserStrategyUtils.invokeAwareMethods( // 调用xxxAware回调方法
                     selector, this.environment, this.resourceLoader, this.registry);
							// 处理DeferredImportSelector
              if (selector instanceof DeferredImportSelector) { 
                  this.deferredImportSelectorHandler.handle(
                        configClass, (DeferredImportSelector) selector);
               }
               else {
                  // currentSourceClass.getMetadata(): 当前配置类的注解元数据
                  String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); // 调用ImportSelector.selectImports方法
                  Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                  // 递归处理
                  processImports(configClass, currentSourceClass, importSourceClasses, false);
               }
            }
           	// ImportBeanDefinitionRegistrar延迟处理
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { 
               Class<?> candidateClass = candidate.loadClass();
               ImportBeanDefinitionRegistrar registrar =
                     BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
               ParserStrategyUtils.invokeAwareMethods( // 调用xxxAware回调方法
                     registrar, this.environment, this.resourceLoader, this.registry);
               // 添加到configClass,构建ConfigurationClass模型,记录ImportBeanDefinitionRegistrar与SourceClass的关系
               configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            }
            else {
               // 如果以上都不成立,当做@Configuration处理
               // 注册导入关系
               this.importStack.registerImport(
                     currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
               processConfigurationClass(candidate.asConfigClass(configClass)); // 递归处理
            }
         }
      }
      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();
      }
   }
}

对于导入类的处理,如果导入类实现了ImportSelector接口且不是DeferredImportSelector实现,则直接调用ImportSelector.selectImport方法得到importClassNames,然后进行递归处理;如果导入类实现了ImportBeanDefinitionRegistrar,则会实例化ImportBeanDefinitionRegistrar实现并添加到ConfigurationClass模型中,会在后续进行处理;其他情况下,会将导入类当做@Configuration配置类处理,进行递归调用。

六、配置类@ImportResource注解处理

// doProcessConfigurationClass方法局部
// Process any @ImportResource annotations 处理配置类上的@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,记录资源与BeanDefinitionReader的对应关系
      configClass.addImportedResource(resolvedResource, readerClass);
   }
}

对于@ImportResource注解,先获取其AnnotationAttributes。然后获取其表示的资源,然后将这些资源添加到ConfigurationClass模型中,会在后续处理。

七、配置类@Bean方法处理

// doProcessConfigurationClass方法局部
// Process individual @Bean methods 处理配置类中的@Bean注解方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
   // 记录BeanMethod到configClass
   configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

首先获取@Bean方法元数据,然后添加到ConfigurationClass模型中,会在后续处理。

获取@Bean方法元数据过程如下:

// @Bean注解方法处理
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
   AnnotationMetadata original = sourceClass.getMetadata();
   // 获取@Bean方法元数据
   Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
   if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
      try {
         // 确定@Bean注解的方法声明顺序
         AnnotationMetadata asm =
               this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
         Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
         if (asmMethods.size() >= beanMethods.size()) {
            Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
            for (MethodMetadata asmMethod : asmMethods) {
               for (MethodMetadata beanMethod : beanMethods) {
                  if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
                     selectedMethods.add(beanMethod);
                     break;
                  }
               }
            }
            if (selectedMethods.size() == beanMethods.size()) {
               // All reflection-detected methods found in ASM method set -> proceed
               beanMethods = selectedMethods;
            }
         }
      }
      catch (IOException ex) {
         logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
         // No worries, let's continue with the reflection metadata we started with...
      }
   }
   return beanMethods;
}

八、处理配置类所实现接口的默认方法

// doProcessConfigurationClass方法局部
// Process default methods on interfaces 处理sourceClass配置类实现的接口上的默认方法
processInterfaces(configClass, sourceClass);
// Register default methods on interfaces implemented by the configuration class. 
// 处理该配置类实现的接口上的默认方法
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
   for (SourceClass ifc : sourceClass.getInterfaces()) { // 获取实现的接口
     // 获取@Bean注解方法
      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);
   }
}

对于配置类实现的接口,首先获取这些接口的@Bean注解方法,然后选出默认方法,添加到ConfigurationClass模型中,会在后续进行处理(注册BeanDefinition)。

九、配置类超类(父类)处理

// doProcessConfigurationClass方法局部
// 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方法会返回父类给上层processConfigurationClass方法,继续处理父类中的配置。

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
   // ...
   // Recursively process the configuration class and its superclass hierarchy.
   SourceClass sourceClass = asSourceClass(configClass); // 获取SourceClass
   do {
      // sourceClass可能是configClass本身或父类
      sourceClass = doProcessConfigurationClass(configClass, sourceClass); 
   }
   while (sourceClass != null);

   this.configurationClasses.put(configClass, configClass);
}

至此,doProcessConfigurationClass方法对配置类进行解析的流程分析结束。

十、读取ConfigurationClass模型并注册BeanDefinitions

然后回到ConfigurationClassPostProcessor.processConfigBeanDefinitions方法的以下代码处:

// ConfigurationClassPostProcessor.processConfigBeanDefinitions方法局部
do {
   parser.parse(candidates); // 解析入口
   parser.validate(); // 校验

   // 得到配置类模型集合
   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());
   }
   this.reader.loadBeanDefinitions(configClasses); // 根据configClasses加载并注册BeanDefinitions
   alreadyParsed.addAll(configClasses); // configClasses添加到已处理的集合

  	// ...省略部分代码
  
}
while (!candidates.isEmpty()); // 如果检查得到的新增的配置类集合不为空,继续处理

在解析完配置类之后,会得到配置类模型集合Set<ConfigurationClass> configClasses。接着使用ConfigurationClassBeanDefinitionReader读取配置类模型,根据配置类模型加载并注册BeanDefinitions。

 this.reader.loadBeanDefinitions(configClasses); // 根据configClasses加载并注册BeanDefinitions
// 读取配置类模型,注册相关的BeanDefinitions
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
   TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
   for (ConfigurationClass configClass : configurationModel) {
      loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
   }
}

// 注册配置类本身的BeanDefinition、@Bean注解方法处理、@ImportResource注解处理、
// ImportBeanDefinitionRegistrar实现处理
private void loadBeanDefinitionsForConfigurationClass(
      ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

   if (trackedConditionEvaluator.shouldSkip(configClass)) { // 是否跳过,如果跳过,移除相关的BeanDefinition
      String beanName = configClass.getBeanName();
      if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
         this.registry.removeBeanDefinition(beanName); // 移除BeanDefinition
      }
      this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
      return;
   }

   if (configClass.isImported()) { // 如果配置类是被导入的,则注册配置类本身的BeanDefinition
      registerBeanDefinitionForImportedConfigurationClass(configClass); 
   }
   for (BeanMethod beanMethod : configClass.getBeanMethods()) {
      loadBeanDefinitionsForBeanMethod(beanMethod); // 注册@Bean注解方法的BeanDefinition
   }

   // @ImportResource注解处理,读取BeanDefinitions
   loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
   // ImportBeanDefinitionRegistrar实现处理
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

根据loadBeanDefinitionsForConfigurationClass方法的逻辑,每个配置类模型的处理主要分为以下4步。

1. 注册配置类本身的BeanDefinition
if (configClass.isImported()) { // 如果配置类是被导入的,则注册配置类本身的BeanDefinition
   registerBeanDefinitionForImportedConfigurationClass(configClass); 
}
// 注册配置类本身的BeanDefinition
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
   AnnotationMetadata metadata = configClass.getMetadata();
   AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

   ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
   configBeanDef.setScope(scopeMetadata.getScopeName()); // 设置scope
   String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
   AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata); // 处理公共注解

   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
   // 创建代理
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
   // 注册BeanDefinition
   this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
   configClass.setBeanName(configBeanName);

   if (logger.isTraceEnabled()) {
      logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
   }
}
2. 注册@Bean注解方法的BeanDefinition
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
   loadBeanDefinitionsForBeanMethod(beanMethod); // 注册@Bean注解方法的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")));
   // 如果配置了name属性,则以name属性值的数组,第一个元素为beanName;否则以方法名为beanName
   String beanName = (!names.isEmpty() ? names.remove(0) : methodName); // 确定beanName

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

   if (metadata.isStatic()) {
      // static @Bean method 静态@Bean方法,则以配置类为beanClass,以当前方法为静态工厂方法处理
      beanDef.setBeanClassName(configClass.getMetadata().getClassName());
      beanDef.setFactoryMethodName(methodName);
   }
   else {
      // instance @Bean method 实例@Bean方法,则以配置类对应的Bean为实例工厂Bean,以当前方法为实例工厂方法处理
      beanDef.setFactoryBeanName(configClass.getBeanName());
      beanDef.setUniqueFactoryMethodName(methodName);
   }
   beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); // 设置装配模式为构造器装配
   beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
         SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

   AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata); // 处理公共注解

   // 以下是@Bean注解相关属性处理
   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;
   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 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));
   }
   this.registry.registerBeanDefinition(beanName, beanDefToRegister); // 注册
}
3. @ImportResource注解处理
// @ImportResource注解处理,读取BeanDefinitions
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
private void loadBeanDefinitionsFromImportedResources(
      Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
   // BeanDefinitionReader实例缓存
   Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();

   importedResources.forEach((resource, readerClass) -> {
      // Default reader selection necessary? 选择默认的BeanDefinitionReader
      if (BeanDefinitionReader.class == readerClass) {
         if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
            // When clearly asking for Groovy, that's what they'll get...
            readerClass = GroovyBeanDefinitionReader.class; // groovy
         }
         else {
            // Primarily ".xml" files but for any other extension as well
            readerClass = XmlBeanDefinitionReader.class; // xmlx
         }
      }

      BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
      if (reader == null) {
         try {
            // Instantiate the specified BeanDefinitionReader 实例化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
      reader.loadBeanDefinitions(resource); // 加载BeanDefinitions
   });
}

对于@ImportResource导入的资源,使用XmlBeanDefinitionReader、GroovyBeanDefinitionReader等加载、注册BeanDefinitions。

4. ImportBeanDefinitionRegistrar实现处理
// ImportBeanDefinitionRegistrar实现处理
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
// ImportBeanDefinitionRegistrar注册BeanDefinitions
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   registrars.forEach((registrar, metadata) ->
         registrar.registerBeanDefinitions(metadata, this.registry));
}

对于ImportBeanDefinitionRegistrar实现,调用其registerBeanDefinitions方法执行其注册BeanDefinition逻辑。

十一、注册ImportStack实例

// ConfigurationClassPostProcessor.processConfigBeanDefinitions方法局部
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
   // 注册ImportStack实例
   sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); 
}

在ConfigurationClassPostProcessor.processConfigBeanDefinitions方法的最后,会注册ImportRegistry实现,即ImportStack实例到BeanFactory,以支持实现了ImportAware接口的配置类。

至此,以ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry为入口的配置类处理流程分析完毕。

十二、@Configuration配置类CGLIB增强

在执行完ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry方法之后,会继续执行ConfigurationClassPostProcessor.postProcessBeanFactory方法,如下所示,进行@Configuration配置类的CGLIB增强。

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

   // @Configuration配置类CGLIB增强
   enhanceConfigurationClasses(beanFactory);
   // 此BeanPostProcessor会将实现了ImportAware接口的类注入 其导入配置类的注解元数据
   beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
// 配置类CGLIB增强,使其拥有调用@Bean方法总是返回一个对象的能力(单例)
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
   Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
   for (String beanName : beanFactory.getBeanDefinitionNames()) {
      BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
      // 只增强@Configuration注解的类
      if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) { // @Configuration注解的Full完全模式的配置类
         // Spring提供的所有BeanDefinition的实现类都继承了AbstractBeanDefinition
         if (!(beanDef instanceof AbstractBeanDefinition)) {
            throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
                  beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
         }
         // 如果已经存在了一个单例实例,那么不会增强它,造成这个现象的原因是非静态的@Bean方法的返回类型
         // 是BeanDefinitionRegistryPostProcessor
         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'.");
         }
         configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
      }
   }
   if (configBeanDefs.isEmpty()) {
      // nothing to enhance -> return immediately
      return;
   }

   // 使用ConfigurationClassEnhancer增强配置类,使其拥有调用@Bean方法总是返回一个对象的能力
   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);
      try {
         // Set enhanced subclass of the user-specified bean class
         Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
         if (configClass != null) {
            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()));
               }
               beanDef.setBeanClass(enhancedClass); // 代理类替换原始的类
            }
         }
      }
      catch (Throwable ex) {
         throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
      }
   }
}

enhanceConfigurationClasses方法中使用了ConfigurationClassEnhancer对配置类进行CGLIB增强处理。ConfigurationClassEnhancer.enhance()方法会使用CGLIB返回配置类的一个代理类,这个代理类拦截了@Bean方法,重复调用这个方法总是返回同一个对象(默认行为,除非指定@Sope),使其拥有单例的能力。

// 增强
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
   if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
      if (logger.isDebugEnabled()) {
         logger.debug(String.format("Ignoring request to enhance %s as it has " +
               "already been enhanced. This usually indicates that more than one " +
               "ConfigurationClassPostProcessor has been registered (e.g. via " +
               "<context:annotation-config>). This is harmless, but you may " +
               "want check your configuration and remove one CCPP if possible",
               configClass.getName()));
      }
     	// 已经增强则直接返回
      return configClass;
   }
   Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader)); // 创建代理类
   if (logger.isTraceEnabled()) {
      logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
            configClass.getName(), enhancedClass.getName()));
   }
   return enhancedClass;
}

private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
	Enhancer enhancer = new Enhancer();
	enhancer.setSuperclass(configSuperClass);
	enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
	enhancer.setUseFactory(false);
	enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
	enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
	enhancer.setCallbackFilter(CALLBACK_FILTER);
	enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
	return enhancer;
}

private Class<?> createClass(Enhancer enhancer) {
	Class<?> subclass = enhancer.createClass();
	Enhancer.registerStaticCallbacks(subclass, CALLBACKS); // 注册拦截器实例
	return subclass;
}

public interface EnhancedConfiguration extends BeanFactoryAware {}

enhancer指定了实现接口为EnhancedConfiguration,此接口继承了BeanFactoryAware接口,所以就拥有了setBeanFactory()方法,因此Spring容器会将持有的BeanFactory通过此方法传递给代理对象。enhancer又配置了一个BeanFactoryAwareGeneratorStrategy,它会给代理类添加一个名为$$beanFactory并且类型为BeanFactory的字段。加上拦截器BeanFactoryAwareMethodInterceptor,结合这三者,BeanFactoryAwareMethodInterceptor起作用的时候就会将$$beanFactory赋值为当前容器,而后代理对象就拥有了Spring容器。

private static final String BEAN_FACTORY_FIELD = "$$beanFactory";

private static class BeanFactoryAwareGeneratorStrategy extends DefaultGeneratorStrategy {
	protected ClassGenerator transform(ClassGenerator cg) throws Exception {
		ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
			@Override
			public void end_class() {
				// 在代理类添加 $$beanFactory Field
				declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
				super.end_class();
			}
		};
		return new TransformingClassGenerator(cg, transformer);
	}
}

enhancer设置了一组拦截器(CALLBACKS),每当执行代理类的一个方法都会经过拦截器,至于选择哪个拦截器是由ConditionalCallbackFilter CALLBACK_FILTER决定的。如下所示,最终由拦截器的isMatch()方法决定是哪个拦截器匹配生效,CALLBACKS是三个Callback实例,分别起到不同的作用。

// 拦截器(方法回调)
private static final Callback[] CALLBACKS = new Callback[] {
		new BeanMethodInterceptor(),
		new BeanFactoryAwareMethodInterceptor(),
		NoOp.INSTANCE
};

// Filter: 方法拦截时选择以上的拦截器
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);


private static class ConditionalCallbackFilter implements CallbackFilter {
   // 回调拦截器
   private final Callback[] callbacks;
   // 回调拦截器类型
   private final Class<?>[] callbackTypes;

   public ConditionalCallbackFilter(Callback[] callbacks) {
      this.callbacks = callbacks;
      this.callbackTypes = new Class<?>[callbacks.length];
      for (int i = 0; i < callbacks.length; i++) {
         this.callbackTypes[i] = callbacks[i].getClass();
      }
   }

   // 选择回调拦截器
   @Override
   public int accept(Method method) {
      for (int i = 0; i < this.callbacks.length; i++) {
         Callback callback = this.callbacks[i];
         // 如果callback不是ConditionalCallback,或者是ConditionalCallback,且匹配方法,则返回当前的callback进行拦截处理
         if (!(callback instanceof ConditionalCallback) || ((ConditionalCallback) callback).isMatch(method)) {
            return i;
         }
      }
      throw new IllegalStateException("No callback available for method " + method.getName());
   }

   public Class<?>[] getCallbackTypes() {
      return this.callbackTypes;
   }
}

当Spring容器调用代理对象的setBeanFactory()方法时,拦截器BeanFactoryAwareMethodInterceptor匹配该方法调用,执行拦截后的操作。

private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

   public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
     	// 找到Field
      Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD); 
      Assert.state(field != null, "Unable to find generated BeanFactory field");
      field.set(obj, args[0]); // 设置value,注入BeanFactory实例

      if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
         // 实际被代理的类如果也实现了BeanFactoryAware,则也注入BeanFactory实例
         return proxy.invokeSuper(obj, args); 
      }
      return null;
   }

  // 如果调用的方法是setBeanFactory,则使用本拦截器拦截,注入BeanFactory实例
   public boolean isMatch(Method candidateMethod) { 
      return isSetBeanFactory(candidateMethod);
   }

   public static boolean isSetBeanFactory(Method candidateMethod) {
      return (candidateMethod.getName().equals("setBeanFactory") && // 方法签名检查、声明类检查
            candidateMethod.getParameterCount() == 1 &&
            BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
            BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
   }
}

BeanFactoryAwareMethodInterceptor.isMatch方法匹配后,执行intercept方法。此方法就是如上所说,将BeanFactory保存到代理对象的$$beanFactory属性,供代理对象使用,因为后面BeanMethodInterceptor拦截器生效的时候会用到。

如果调用目标对象的方法不是setBeanFactory方法并且是@Bean方法,则使用BeanMethodInterceptor加强(代理)此方法。值得注意的是,如果请求的bean是FactoryBean,则创建一个子类代理来拦截对getObject()的调用并返回任何缓存的bean实例。作用域代理FactoryBean是一种特殊情况,不应该进一步代理。

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

	public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs, MethodProxy cglibMethodProxy) throws Throwable {

		// 根据BEAN_FACTORY_FIELD字段,从代理类实例获取BeanFactory实例
    // enhancedConfigInstance 代理类实例
		ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance); 
    // 确定 Bean name
		String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod); 

		if (BeanAnnotationHelper.isScopedProxy(beanMethod)) { // 是否作用域代理
			// 获取作用域代理的目标bean的bean name  scopedTarget.beanName
			String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
			if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
				beanName = scopedBeanName;
			}
		}

		if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
				factoryContainsBean(beanFactory, beanName)) {
      // 获取FactoryBean实例
			Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName); 
			if (factoryBean instanceof ScopedProxyFactoryBean) {
				// 对于factory bean,如果显式的设置了@Scope属性proxyMode为代理模式,则不需要进一步代理
			}
			else {
				// 生成FactoryBean代理
				return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
			}
		}

		// Spring通过工厂方法创建时会保存创建对象的工厂方法,所以说第一次调用创建对象方法不会被拦截
		if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
			// 直接使用工厂方法创建对象(会在Spring容器缓存该单例对象)
			return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
		}

		// 如果不是第一次调用此方法,从容器中直接获取达到单例目的
		return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
	}

	private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
			ConfigurableBeanFactory beanFactory, String beanName) {

		boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
		try {
			if (alreadyInCreation) {
				beanFactory.setCurrentlyInCreation(beanName, false);
			}
			boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
			if (useArgs && beanFactory.isSingleton(beanName)) {
				for (Object arg : beanMethodArgs) {
					if (arg == null) {
						useArgs = false;
						break;
					}
				}
			}
			// 获取实例
			Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
					beanFactory.getBean(beanName));
			if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
				if (beanInstance.equals(null)) {
					if (logger.isDebugEnabled()) {
						logger.debug(String.format("@Bean method %s.%s called as bean reference " +
								"for type [%s] returned null bean; resolving to null value.",
								beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
								beanMethod.getReturnType().getName()));
					}
					beanInstance = null;
				}
				else {
					String msg = String.format("@Bean method %s.%s called as bean reference " +
							"for type [%s] but overridden by non-compatible bean instance of type [%s].",
							beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
							beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
					try {
						BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
						msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
					}
					catch (NoSuchBeanDefinitionException ex) {
					}
					throw new IllegalStateException(msg);
				}
			}
			// 获取目前正在调用的工厂方法(可能是其他@Bean方法调用的获取当前beanInstance的动作)
			Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
			if (currentlyInvoked != null) {
				String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
				beanFactory.registerDependentBean(beanName, outerBeanName); // 注册依赖关系
			}
			return beanInstance;
		}
		finally {
			if (alreadyInCreation) {
				beanFactory.setCurrentlyInCreation(beanName, true);
			}
		}
	}

	public boolean isMatch(Method candidateMethod) {
		return (candidateMethod.getDeclaringClass() != Object.class &&
				!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
				BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
	}
}

如果当前调用的工厂方法就是该@Bean方法(@Bean方法定义的Bean一般是单例,会在容器初始化时预初始化这些Bean,使用的是工厂方法初始化的方式,这是第一次调用@Bean方法创建单例),intercept方法会进入如下的分支,直接使用工厂方法创建对象(会在Spring容器缓存该单例对象)。后续再次请求该@Bean方法对应的单例对象时,会直接从容器单例缓存中返回。

// 判断method是否是当前正在调用的工厂方法
private boolean isCurrentlyInvokedFactoryMethod(Method method) { 
  // 当前正在调用的工厂方法
	Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod(); 
	return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
			Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
}
// Spring通过工厂方法创建对象时会保存创建对象的工厂方法(ThreadLocal)
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
	// 直接使用工厂方法创建对象(会在Spring容器缓存该单例对象)
	return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}


如果当前调用的工厂方法不是该@Bean方法(一般在容器预初始化阶段),可能是其他@Bean方法间接依赖该@Bean方法的对象,由其他@Bean方法间接调用该@Bean方法,因此直接从容器中获取,达到单例目的。

return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);

// resolveBeanReference方法局部
// 获取实例
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
		beanFactory.getBean(beanName));

至此,@Configuration配置类CGLIB增强逻辑分析结束。

参考文章