Spring源码之ConfigurationClassPostProcessor类解读

目录

1. postProcessBeanDefinitionRegistry()

(1)@Conditional注解解析

(2)@Component、@ComponentScan、@Import、@ImportSource等注解的解析

a. @Component、@ComponentScan、@Import、@ImportSource解析

b. @Configuration解析

c. @ComponentScans解析

d. 内部类处理 

d. @PropertySource解析

e. @Import解析

2. postProcessBeanFactory()


         现如今,我们在使用Spring框架时,基本都是基于注解的方式进行Bean的注入,如:@PropertySource、@ComponentScan、@Bean、@Import、@ImportSource、@Configuration、ImportSelector,它们的解析,都离不开ConfigurationClassPostProcessor类,这些注解就是去扫描(或引入),把扫描(或引入)的类放到Spring容器,变成BeanDefinition。

        之前我们都是通过基于XML的方式注册Spring上下文,现在,通过注解上下文的方式已经大行其道,如下:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);

        通过@ComponentScan注解将包路径导入:

@Component
@ComponentScan(value = "com.baec.kieasar")
public class ScanBean {
 
}

        或者:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.baec.kieasar");

        我们看AnnotationConfigApplicationContext的构造函数:

public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
   super(beanFactory);
   this.reader = new AnnotatedBeanDefinitionReader(this);
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

        进入AnnotatedBeanDefinitionReader的构造函数:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
   this(registry, getOrCreateEnvironment(registry));
}

        进入this():

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   Assert.notNull(environment, "Environment must not be null");
   this.registry = registry;
   this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
   AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

        进入AnnotationConfigUtils.registerAnnotationConfigProcessors()方法

        所属类:org.springframework.context.annotation.AnnotationConfigUtils

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
   registerAnnotationConfigProcessors(registry, null);
}

        ConfigurationClassPostProcessor就是在这里注册进来的

RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			// 设置beanFactory的OrderComparator为AnnotationAwareOrderComparator
			// 它是一个Comparator(比较器),用来排序,比如new ArrayList<>().sort(Comparator)
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			// ContextAnnotationAutowireCandidateResolver类是注解候选解析器(主要处理@Lazy),用来推断某个Bean是否需要依赖注入
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

		// 注册ConfigurationClassPostProcessor类型的BeanDefinition
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// 注册AutowiredAnnotationBeanPostProcessor类型的BeanDefinition
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		// 注册CommonAnnotationBeanPostProcessor类型的BeanDefinition
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		// 注册PersistenceAnnotationBeanPostProcessor类型的BeanDefinition
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// 注册EventListenerMethodProcessor类型的BeanDefinition,用来处理@EventListener注解
		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}

		// 注册DefaultEventListenerFactory类型的BeanDefinition,用来处理@EventListener注解
		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}

        首先,我们先看一下ConfigurationClassPostProcessor类的继承关系:

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

        该类实现了BeanDefinitionRegistryPostProcessor接口,用来操作(注册)BeanDefinition,并加入到BeanDefinitionRegistry中。PriorityOrdered接口是用来做排序的,它继承Ordered接口,重写了getOrder()方法:

@Override
// 设定执行顺序,值越小,先执行
public int getOrder() {
   return Ordered.LOWEST_PRECEDENCE;  // within PriorityOrdered
}

1. postProcessBeanDefinitionRegistry()

        同时实现了BeanDefinitionRegistyPostProcessor接口,必然会实现postProcessBeanDefinitionRegistry()方法,注册BeanDefinition,扫描配置类,我们先看这个方法:

/**
 * Derive further bean definitions from the configuration classes in the registry.
 * 这是BeanDefinitionRegistryPostProcessor接口BeanFactoryPostProcessor的方法,进行了重写
 */
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
   int registryId = System.identityHashCode(registry);
   if (this.registriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
   }
   if (this.factoriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + registry);
   }
   this.registriesPostProcessed.add(registryId);
   // TODO 核心逻辑解析配置类,重点看---->
   processConfigBeanDefinitions(registry);
}

        进入本类的processConfigBeanDefinitions()方法:

/**
 * Build and validate a configuration model based on the registry of
 * {@link Configuration} classes.
 * 在这个方法中就是对所有的beanDefinition操作(解析)
 */
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
   // 获取所有的beanNames
   String[] candidateNames = registry.getBeanDefinitionNames();

   for (String beanName : candidateNames) {
      BeanDefinition beanDef = registry.getBeanDefinition(beanName);
      // 如果有该标识就不再处理,"configurationClass" 表示有那些注解,如:@Configuration
      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,如果是,则放入configCandidates
      else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
         configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
      }
   }

   // Return immediately if no @Configuration classes were found
   // 如果容器为空,即找不到@Configuration类,则立即返回
   if (configCandidates.isEmpty()) {
      return;
   }

   // Sort by previously determined @Order value, if applicable
   // 对需要处理的BeanDeanDefinition排序,值越小越靠前
   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 sbr = null;
   if (registry instanceof SingletonBeanRegistry) {
      sbr = (SingletonBeanRegistry) registry;
      if (!this.localBeanNameGeneratorSet) {
         BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
               AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
         if (generator != null) {
            this.componentScanBeanNameGenerator = generator;
            this.importBeanNameGenerator = generator;
         }
      }
   }

   if (this.environment == null) {
      this.environment = new StandardEnvironment();
   }

   // 解析配置类,BeanDefinition解析器————ConfigurationClassParser
   // Parse each @Configuration class
   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 {
      StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
      // TODO 解析的核心流程,重要程度:5
      //  先收集,如@Import、@ComponentScan、@Bean、ImportSelector,最终封装成BeanDefinition
      // 解析,会先把BeanDefinitionHolder封装成ConfigurationClass
	  // 在这个过程中会进行扫描、导入等步骤,从而找到其他的ConfigurationClass
      parser.parse(candidates);
      parser.validate();

      // ConfigurationClass相当于截止到当前,解析得到的所有配置类(包括本身)
      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());
      }
      // TODO 再调用,上面的parse()方法对一些注解没有扫描到,所以在这里进行调用。
      // 解析,会先把BeanDefinitionHolder封装成ConfigurationClass
	  // 在这个过程中会进行扫描、导入等步骤,从而找到其他的ConfigurationClass
      this.reader.loadBeanDefinitions(configClasses);
      // 已经解析完的类,再一个递归进来不必重复处理
      alreadyParsed.addAll(configClasses);
      processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

      candidates.clear();
      // 比较差异,如果发现有新的BeanDefiniton,再走一遍解析流程
      if (registry.getBeanDefinitionCount() > candidateNames.length) {
         String[] newCandidateNames = registry.getBeanDefinitionNames();
         Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
         Set<String> alreadyParsedClasses = new HashSet<>();
         for (ConfigurationClass configurationClass : alreadyParsed) {
            alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
         }
         for (String candidateName : newCandidateNames) {
            if (!oldCandidateNames.contains(candidateName)) {
               BeanDefinition bd = registry.getBeanDefinition(candidateName);
               // 检查多出来的BeanDefinition是否为配置类,是否需要解析
               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();
   }
}

        进入parse()方法:

        所属类:org.springframework.context.annotation.ConfigurationClassParser

// 解析过程
public void parse(Set<BeanDefinitionHolder> configCandidates) {
   for (BeanDefinitionHolder holder : configCandidates) {
      BeanDefinition bd = holder.getBeanDefinition();
      try {
         // 通过扫描注解方式得到的BeanDefinition
         if (bd instanceof AnnotatedBeanDefinition) {
             // 看这个方法*****
            parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
         }
         // 不是通过扫描注解得到的BeanDefinition
         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);
      }
   }
    // TODO 处理DeferredImportSelector接口的解析,当前所有的配置类解析之后才执行
    // DeferredImportSelector表示推迟的ImportSelector,正常的ImportSelector是在解析配置类过程中执行的
   this.deferredImportSelectorHandler.process();
}

        进入本类的parse()方法:

        所属类:org.springframework.context.annotation.ConfigurationClassParser

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
   // 把metadata对象和beanName封装成ConfigurationClass对象
   processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

        进入本类的processConfigurationClass()方法,这里是真正的解析逻辑:

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) 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()) {
         // 如果一个类被两个类import了,就符合这个条件,加到importBy这个属性中
         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.
   // 这个对象可以理解为跟类或者跟接口对应,然后把metadata对象包装进去
   SourceClass sourceClass = asSourceClass(configClass, filter);
   do {
      // TODO 核心代码-->
      sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
   }
   while (sourceClass != null);
    // 收集完之后放到Map中
   this.configurationClasses.put(configClass, configClass);
}

(1)@Conditional注解解析

        首先解析的是@Conditional注解,@Conditional注解在Springboot中使用较多,作用就是设置该类实例化的条件,如:

@Conditional(value = {CustomCondition.class})
@Primary
@Bean
public Lison lison() {
    return new Lison();
}

        Lison类实例化需要依赖CustomCondition,也可以是数组,被依赖的类CustomCondition需要实现Condition接口,实现matches()方法:

public class CustomCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return true;
    }
}

        进入@Conditional注解的解析方法shouldSkip():

public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
   if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
      return false;
   }

   if (phase == null) {
      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<>();
   // 获取@Conditional注解的value值
   for (String[] conditionClasses : getConditionClasses(metadata)) {
      for (String conditionClass : conditionClasses) {
         // 反射实例花Condition对象
         Condition condition = getCondition(conditionClass, this.context.getClassLoader());
         conditions.add(condition);
      }
   }
   // 排序(支持Order接口、@Order注解)
   AnnotationAwareOrderComparator.sort(conditions);

   for (Condition condition : conditions) {
      ConfigurationPhase requiredPhase = null;
      if (condition instanceof ConfigurationCondition) {
         requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
      }
      // 循环调用每一个condition的matches()方法
      if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
         return true;
      }
   }

   return false;
}

(2)@Component、@ComponentScan、@Import、@ImportSource等注解的解析

        回到processConfigurationClass()方法,进入核心代码doProcessConfigurationClass() 方法:

        所属类:org.springframework.context.annotation.ConfigurationClassParser

 /*
  * TODO 注解解析核心方法   SourceClass代表对类的封装,负责的方向不一样,里面有个metaData对象
  */
@Nullable
protected final SourceClass doProcessConfigurationClass(
      ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
      throws IOException {

   // 判断类上面是否有@Component注解
   if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
      // Recursively process any member (nested) classes first
      // TODO 递归处理有@Component注解的【对内部类的处理】
      processMemberClasses(configClass, sourceClass, filter);
   }

   // Process any @PropertySource annotations
   // 处理@PropertySources和@PropertySource注解
   for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
         sourceClass.getMetadata(), PropertySources.class,
         org.springframework.context.annotation.PropertySource.class)) {
      if (this.environment instanceof ConfigurableEnvironment) {
         // TODO 核心逻辑———>
         processPropertySource(propertySource);
      }
      else {
         logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
               "]. Reason: Environment must implement ConfigurableEnvironment");
      }
   }

   // Process any @ComponentScan annotations
   // 处理@ComponentScans和@ComponentScan注解,从sourceClass.getMetadata()拿到注解,放到Set容器
   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
         // TODO 下面这个parse()方法中的逻辑,跟<component-scan>自定义标签解析的逻辑类似,
         // 通过ClassPathBeanDefinitionScanner去扫描,得到BeanDefiniiton,注册到Spring容器
         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
         // 这里递归扫描到@Component生成beanDefinition后,又递归去检验类上面是否有特殊注解
         for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
            BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
            if (bdCand == null) {
               bdCand = holder.getBeanDefinition();
            }
            // 判断是否是候选的BeanDefinition,如果是,则parse(),又是递归处理
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
               parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
         }
      }
   }

   // Process any @Import annotations
   // TODO 处理@Import注解,getImports(sourceClass)方法用来收集类上面的@Import注解,并封装成SourceClass
   processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

   // Process any @ImportResource annotations
   // 处理@ImportResource注解,作用不大,加载xml文件
   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);
         // 建立xml文件和reader的映射关系
         configClass.addImportedResource(resolvedResource, readerClass);
      }
   }

   // Process individual @Bean methods
   // (重点)处理@Bean注解,收集有@Bean注解的方法,sourceClass为当前类
   Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
   for (MethodMetadata methodMetadata : beanMethods) {
      // 加入到ConfigurationClass中
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
   }

   // Process default methods on interfaces
   // 处理有@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;
}

         上面方法我们用一个图来归纳:

a. @Component、@ComponentScan、@Import、@ImportSource解析

        对@Component、@ComponentScan、@Import、@ImportSource注解的判断,在isConfigurationCandidate()方法中:

        所属类:org.springframework.context.annotation.ConfigurationClassUtils

	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、@ImportSource注解中的一个,就是lite配置类
		for (String indicator : candidateIndicators) {
			if (metadata.isAnnotated(indicator)) {
				return true;
			}
		}

		// Finally, let's look for @Bean methods...
		// 如果存在@Bean注解的方法,就是lite配置类
		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;
		}
	}
abstract class ConfigurationClassUtils {

	public static final String CONFIGURATION_CLASS_FULL = "full";

	public static final String CONFIGURATION_CLASS_LITE = "lite";

	public static final String CONFIGURATION_CLASS_ATTRIBUTE =
			Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");

	private static final String ORDER_ATTRIBUTE =
			Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "order");


	private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class);

	private static final Set<String> candidateIndicators = new HashSet<>(8);

	static {
		candidateIndicators.add(Component.class.getName());
		candidateIndicators.add(ComponentScan.class.getName());
		candidateIndicators.add(Import.class.getName());
		candidateIndicators.add(ImportResource.class.getName());
	}

b. @Configuration解析

        对@Configuration注解的类,Spring判依据是以下几种:

  • 如果有@Configuration注解的类,并且proxyBeanMethods为true或null(默认)时,就是Full配置类;
  • 如果有@Configuration注解,但proxyBeanMethods为false时,为lite配置类;
  • 如果不存在@Configuration注解,但只要存在@Component、@ComponentScan、@Import、@ImportSource,就是lite配置类;
  • 如果不存在@Configuration注解,但只要有@Bean注解的方法,就是lite配置类。

c. @ComponentScans解析

         会创建一个ClassPathBeanDefinitionScanner扫描器,调用doScan()方法:

        所属类:org.springframework.context.annotation.ClassPathBeanDefinitionScanner

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
   for (String basePackage : basePackages) {
      // 根据扫描路径,得到BeanDefinition
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      // 解析class
      for (BeanDefinition candidate : candidates) {
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
         if (candidate instanceof AbstractBeanDefinition) {
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
            // 解析@lazy、@Primary、@DependsOn、@Role、@Description
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         // 检查Spring容器是否已经存在beanName
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            // 注册
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

        在doProcessConfigurationClass()方法,只有@ComponentScan注解的解析,会通过扫描生成BeanDefinition,其他注解都是添加到了ConfigurationClass类的置属性,(此时还没有解析)。

d. 内部类处理 

        看本类的processMemberClasses(configClass, sourceClass, filter),处理有@Component注解的,这是对内部类的处理:

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

   // 获取该类的内部类并包装成sourceClass对象,可以进去看看getMemberClasses()方法
   Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
   if (!memberClasses.isEmpty()) {
      List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
      for (SourceClass memberClass : memberClasses) {
         // 如果是需要处理的,有@Bean、@Component等注解
         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 {
               // candidate是子类,configClass是父类,candidate是configClass的内部类,递归处理
               processConfigurationClass(candidate.asConfigClass(configClass), filter);
            }
            finally {
               this.importStack.pop();
            }
         }
      }
   }
}

        ConfigurationClass类是用来封装配置类的,我们看一下它的成员属性:

// 该类是对一个类的包装,收集注解的作用(也包括对内部类)
final class ConfigurationClass {

    // 类中的基本源信息,类、方法、注解信息
    private final AnnotationMetadata metadata;
    // 类中流的封装
    private final Resource resource;
    
    @Nullable
    private String beanName;
    // 代表由哪个类导入进来的,装的是被引用来或者外部类
    private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
    // 如果所在类有@Bean注解的方法,放在这个容器中
    private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
    // 如果所在类有@ImportedResources注解,放到这个容器中
    private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
          new LinkedHashMap<>();
    // 如果所在类实现了ImportBeanDefinitionRegistrar接口,放在这个容器中
    private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
          new LinkedHashMap<>();

d. @PropertySource解析

        进入本类的 processPropertySource(propertySource)方法,把配置文件解析出来放到environment中:

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

   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中的配置值属性,封装成Properties对象,并创建PropertySource对象加入到Environment
         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;
         }
      }
   }
}

         SourceClass的组成:

private class SourceClass implements Ordered {

   private final Object source;  // Class or MetadataReader

   private final AnnotationMetadata metadata;

e. @Import解析

        @Imprt注解的作用就是将某个类导入到Spring的容器,并将其实例化。例如:

@Component
// Import虽然是实例化一个类,Import进来的类可以实现一些接口,如:ImportSelector和ImportBeanDefinitionRegistar接口,
// 然后我们可以调用接口中的方法,但是通过@Component注解注入的类如果实现了这些接口,却不能调用其方法。
@Import(DeferredImportSelectorDemo.class)
// @Import({DeferredImportSelectorDemo.class, LisonSelectImport.class, AwareBean.class})
@EnableAspectJAutoProxy
public class ImportBean {
}

        例子中的ImportBean加了@Imprt注解,解析流程就是把ImportBean类包装成SourceClass对象,然后从metadata方法拿到@Import注解,并拿到它的value值,放到Set容器中。value值也可以是数组,导入多个类。

public class LisonSelectImport implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        MergedAnnotations annotations = importingClassMetadata.getAnnotations();
        MergedAnnotation<EnableAspectJAutoProxy> eas = annotations.get(EnableAspectJAutoProxy.class);

        Object proxyTargetClass = eas.getValue("proxyTargetClass").get();
        // 类的完整限定名,
        return new String[]{Jack.class.getName()};
    }
}

        同时也可以拿到引入的这个类ImportBean上面的注解信息,如:@EnableAspectJAutoProxy开启切面功能的注解,Springboot自动配置就是这样实现的。

        进入@Import注解解析的核心方法processImports():

        所属类:本类org.springframework.context.annotation.ConfigurationClassParser

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();
               // 反射实例化
               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) {
                  // 比较复杂,Springboot中自动配置用到
                  this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
               }
               else {
                  // 调用ImportSelectors()方法,返回所有需要import到Spring容器的beanName,这里会调到自己写的实现类方法,返回的是类的完整限定名。
                  // selectImports()方法是在收集之前调用的
                  String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                  Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                  // 递归处理,有时import进来的类又有@Import注解
                  processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
               }
            }
            // 如果@Import的类是ImportBeanDefinitionRegistrar类型
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
               // Candidate class is an ImportBeanDefinitionRegistrar ->
               // delegate to it to register additional bean definitions
               Class<?> candidateClass = candidate.loadClass();
               // 反射实例化
               ImportBeanDefinitionRegistrar registrar =
                     ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                           this.environment, this.resourceLoader, this.registry);
               // 加入到ImportBeanDefinitionRegistrar容器中,这里还没有调用registerBeanDefinitions(),在收集之后调用该接口的实现方法
               // addImportBeanDefinitionRegistrar()维护了一个实现ImportBeanDefinitionRegistrar接口的实例和该类的AnnotationMetadata的映射关系
               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进来的类有其他注解,则进入这里,递归调用进行解析
               processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
            }
         }
      }

        接下来回到processConfigBeanDefinitions()方法,看this.reader.loadBeanDefinitions()方法,这是对@Bean、@ImportedResource、ImportBeanDefinitionRegistrar处理逻辑,解析注解的方法。 配置类解析完成之后会加到当前ConfigurationClass对应的属性中,接下来才会进一步解析(或构建)成BeanDefiniton。

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
   TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
   for (ConfigurationClass configClass : configurationModel) {
      // 注解收集,为类本身及其有@Bean注解的方法封装成BeanDefinition
      loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
   }
}

        这个方法主要就是解析配置类生成BeanDefinition。

private void loadBeanDefinitionsForConfigurationClass(
      ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
   // 是否要跳过
   if (trackedConditionEvaluator.shouldSkip(configClass)) {
      String beanName = configClass.getBeanName();
      if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
         this.registry.removeBeanDefinition(beanName);
      }
      this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
      return;
   }

   // @Import进来的类,和内部类走这里变成BeanDefinition
   if (configClass.isImported()) {
      registerBeanDefinitionForImportedConfigurationClass(configClass);
   }
   // @Bean注解的方法变成BeanDefinition
   for (BeanMethod beanMethod : configClass.getBeanMethods()) {
      loadBeanDefinitionsForBeanMethod(beanMethod);
   }
   // 处理@ImportResource注解,xml解析流程
   loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
   // 处理ImportBeanDefinitionRegistrar接口,调用registrerBeanDefinitions()方法
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

        进入loadBeanDefinitionsForBeanMethod():

        所属类:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader

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

   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")));
   String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

   // Register aliases even when overridden
   for (String alias : names) {
      this.registry.registerAlias(beanName, alias);
   }

   // Has this effectively been overridden before (e.g. via XML)?
   // 如果出现重复的@Bean注解的方法名(比如方法重载),则return,不会生成新的
   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.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

   if (metadata.isStatic()) {
      // static @Bean method
      if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
         beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
      }
      else {
         beanDef.setBeanClassName(configClass.getMetadata().getClassName());
      }
      beanDef.setUniqueFactoryMethodName(methodName);
   }
   else {
      // instance @Bean method
      beanDef.setFactoryBeanName(configClass.getBeanName());
      beanDef.setUniqueFactoryMethodName(methodName);
   }

   if (metadata instanceof StandardMethodMetadata) {
      beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
   }

   beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
   beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
         SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

   AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

   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));
   }
   // 把解析出来的BeanDefiniton注册进去,这里会检查是否允许覆盖
   this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
   if (!this.registry.containsBeanDefinition(beanName)) {
      return false;
   }
   BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);

   // Is the existing bean definition one that was created from a configuration class?
   // -> allow the current bean method to override, since both are at second-pass level.
   // However, if the bean method is an overloaded case on the same configuration class,
   // preserve the existing bean definition.
   // 如果@Bean对应的beanName已经存在BeanDefinition,那么则把此BeanDefinition的isFactoryMethodUnique设置为false
   // 后续根据此BeanDefinition取创建Bean时,就知道不止一个
   if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
      ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
      if (ccbd.getMetadata().getClassName().equals(
            beanMethod.getConfigurationClass().getMetadata().getClassName())) {
         if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
            ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());
         }
         return true;
      }
      else {
         return false;
      }
   }

   // A bean definition resulting from a component scan can be silently overridden
   // by an @Bean method, as of 4.2...
   if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
      return false;
   }

   // Has the existing bean definition bean marked as a framework-generated bean?
   // -> allow the current bean method to override it, since it is application-level
   if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
      return false;
   }

   // At this point, it's a top-level override (probably XML), just having been parsed
   // before configuration class processing kicks in...
   if (this.registry instanceof DefaultListableBeanFactory &&
         !((DefaultListableBeanFactory) this.registry).isAllowBeanDefinitionOverriding()) {
      throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
            beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
   }
   if (logger.isDebugEnabled()) {
      logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
            "already exists. This top-level bean definition is considered as an override.",
            beanMethod, beanName));
   }
   return true;
}

         进入本类的isOverriddenByExistingDefinition(),判断是否重复扫描的情况:

protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
   if (!this.registry.containsBeanDefinition(beanName)) {
      return false;
   }
   BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);

   // Is the existing bean definition one that was created from a configuration class?
   // -> allow the current bean method to override, since both are at second-pass level.
   // However, if the bean method is an overloaded case on the same configuration class,
   // preserve the existing bean definition.
   // ConfigurationClassBeanDefinition是有@Bean注解方法解析后的BeanDefiniton,
   // 如果@Bean对应的beanName已经存在BeanDefinition,那么则把此BeanDefinition的isFactoryMethodUnique设置为false
   // 后续根据此BeanDefinition取创建Bean时,就知道不止一个
   if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
      ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
      if (ccbd.getMetadata().getClassName().equals(
            beanMethod.getConfigurationClass().getMetadata().getClassName())) {
         if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
            ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());
         }
         return true;
      }
      else {
         return false;
      }
   }

   // A bean definition resulting from a component scan can be silently overridden
   // by an @Bean method, as of 4.2...
   // ScannedGenericBeanDefinition是扫描后得到的BeanDefinition
   if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
      return false;
   }

   // Has the existing bean definition bean marked as a framework-generated bean?
   // -> allow the current bean method to override it, since it is application-level
   if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
      return false;
   }

   // At this point, it's a top-level override (probably XML), just having been parsed
   // before configuration class processing kicks in...
   if (this.registry instanceof DefaultListableBeanFactory &&
         !((DefaultListableBeanFactory) this.registry).isAllowBeanDefinitionOverriding()) {
      throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
            beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
   }
   if (logger.isDebugEnabled()) {
      logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
            "already exists. This top-level bean definition is considered as an override.",
            beanMethod, beanName));
   }
   return true;
}
  • @Bean注解的Bean会覆盖@Component注解的;
  • 如果都是@Bean注解的,覆盖;
  • @Component注解重复了,报错。

        前面的方法扫描和增强都做完了,得到了许多BeanDefinition,但是Bean的实例化对象还没生成,@Bean注解对应的方法还没调用,它是在创建Bean,实例化的时候,推断构造方法那儿才会调用。 

2. postProcessBeanFactory()

        接着看ConfigurationClassPostProcessor类的另外一个方法postProcessBeanFactory(),这是BeanFactoryPostProcessor接口的方法,该接口相当于BeanFactory的后置处理器,这里进行了重写了该方法,对有@Configuration注解的类生成代理:

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);
   beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

        进入enhanceConfigurationClasses()方法:

        所属类:org.springframework.context.annotation.ConfigurationClassPostProcessor

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
   Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
   // 遍历,根据beanName找出配置类
   for (String beanName : beanFactory.getBeanDefinitionNames()) {
      BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
      Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
      MethodMetadata methodMetadata = null;
      if (beanDef instanceof AnnotatedBeanDefinition) {
         methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
      }
      if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
         // Configuration class (full or lite) or a configuration-derived @Bean method
         // -> resolve bean class at this point...
         AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
         // 如果没有加载的话就去加载类
         if (!abd.hasBeanClass()) {
            try {
               abd.resolveBeanClass(this.beanClassLoader);
            }
            catch (Throwable ex) {
               throw new IllegalStateException(
                     "Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
            }
         }
      }
      // 判断前面解析配置类得到的configClassAttr属性是否为full,如果是,则加入configBeanDefs容器
      if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
         if (!(beanDef instanceof AbstractBeanDefinition)) {
            throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
                  beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
         }
         else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
            logger.info("Cannot enhance @Configuration bean definition '" + beanName +
                  "' since its singleton instance has been created too early. The typical cause " +
                  "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
                  "return type: Consider declaring such methods as 'static'.");
         }
         configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
      }
   }
   if (configBeanDefs.isEmpty()) {
      // nothing to enhance -> return immediately
      return;
   }

   // 对属性为full的配置类,生成代理类,并设置到BeanDefinition中
   ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
   for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
      AbstractBeanDefinition beanDef = entry.getValue();
      // If a @Configuration class gets proxied, always proxy the target class
      beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
      // Set enhanced subclass of the user-specified bean class
      Class<?> configClass = beanDef.getBeanClass();
      // 生成配置类的代理对象
      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);
      }
   }
}

        进入enhance()方法:

        所属类:org.springframework.context.annotation.ConfigurationClassEnhancer

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

        看本类的createClass()方法:

private Class<?> createClass(Enhancer enhancer) {
   Class<?> subclass = enhancer.createClass();
   // Registering callbacks statically (as opposed to thread-local)
   // is critical for usage in an OSGi environment (SPR-5932)...
   Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
   return subclass;
}

        使用动态代理进行回调:

// The callbacks to use. Note that these callbacks must be stateless.
private static final Callback[] CALLBACKS = new Callback[] {
      new BeanMethodInterceptor(),
      new BeanFactoryAwareMethodInterceptor(),
      NoOp.INSTANCE
}

        BeanMethodInterceptor是ConfigurationClassEnhancer的内部类,会执行BeanMethodInterceptor拦截器类的intercept()方法:

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

   /**
    * Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
    * existence of this bean object.
    * @throws Throwable as a catch-all for any exception that may be thrown when invoking the
    * super implementation of the proxied method i.e., the actual {@code @Bean} method
    */
   @Override
   @Nullable
   public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
            MethodProxy cglibMethodProxy) throws Throwable {

      ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
      String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

      // Determine whether this bean is a scoped-proxy
      if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
         String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
         if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
            beanName = scopedBeanName;
         }
      }

      // To handle the case of an inter-bean method reference, we must explicitly check the
      // container for already cached instances.

      // First, check to see if the requested bean is a FactoryBean. If so, create a subclass
      // proxy that intercepts calls to getObject() and returns any cached bean instance.
      // This ensures that the semantics of calling a FactoryBean from within @Bean methods
      // is the same as that of referring to a FactoryBean within XML. See SPR-6602.
      if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
            factoryContainsBean(beanFactory, beanName)) {
         Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
         if (factoryBean instanceof ScopedProxyFactoryBean) {
            // Scoped proxy factory beans are a special case and should not be further proxied
         }
         else {
            // It is a candidate FactoryBean - go ahead with enhancement
            return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
         }
      }

      // 如果代理对象执行的方法是正在创建Bean的工厂方法,执行对应的方法得到对象作为Bean
      if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
         // The factory is calling the bean method in order to instantiate and register the bean
         // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
         // create the bean instance.
         if (logger.isInfoEnabled() &&
               BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
            logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
                        "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
                        "result in a failure to process annotations such as @Autowired, " +
                        "@Resource and @PostConstruct within the method's declaring " +
                        "@Configuration class. Add the 'static' modifier to this method to avoid " +
                        "these container lifecycle issues; see @Bean javadoc for complete details.",
                  beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
         }
         // 注意这里传入的是代理对象,相当于执行目标对象的方法
         return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
      }
      // 如果代理对象执行的方法不是正在创建Bean的方法,那就直接根据方法的name去Spring容器中获取(getBean()方法)
      return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
   }

        注意:如果有@Configuration注解的配置类里面存在@Bean注解的方法,在实例化执行invoke()方法时会通过代理对象执行方法,例如:

@Configuration
public class ConverterConfig {
    
    @Bean
    public UserService userService(){
        kieasar();
        return new UserService();
    }

    @Bean
    public Kieasar kieasar() {
        return new Kieasar();
    }
}

         上面的例子中,ConverterConfig的代理类在执行userService()方法会先进行判断,看是否为创建Bean的方法,如果是,则进行创建UserService的实例,相当于执行目标对象的方法,就会进入cglibMethodProxy.invokeSuper(),调用被代理对象的方法。

        然后,代理对象接着执行userService()里面的kieasar()方法时,虽然该方法加了@Bean注解,但此时正在执行的是创建userService实例的userService()方法,所以isCurrentlyInvokedFactoryMethod()结果为false,会执行最后一行resolveBeanReference(),执行getBean()方法,根据方法的名字kieasar去容器中获取Kieasar对象的实例。 

        但是,Spring在创建Kieasar这个Bean时,如果当前执行的方法正好是kieasar()方法(也就是创建Kieasar实例的方法),此时isCurrentlyInvokedFactoryMethod()结果为true,执行cglibMethodProxy.invokeSuper(),即被代理对象的方法。

        ConfigurationClassPostProcessor类的解析流程图:

         最后,总结一下ConfigurationClassPostProcessor类的解析过程:

1. 在启动Spring时,需要传入一个ScanBean.class给ApplicationContext,ApplicationContext会根据ScanBean类封装为一个BeanDefinition,我们把它称为配置类BeanDefinition。

2. ConfigurationClassPostProcessor会把配置类BeanDefinition(ScanBean)取出来。

3. 构造一个ConfigurationClassParser用来解析配置类BeanDefinition,并且会生成一个配置类对象ConfigurationClass。

4. 如果配置类上存在@Component注解,那么解析配置类中的内部类(这里有递归,如果内部类也是配置类的话)。

5. 如果配置类上存在@PropertySource注解,那么则解析该注解,并得到PropertySource对象,并添加到environment中去。

6. 如果配置类上存在@ComponentScan注解,那么则解析该注解,进行扫描,扫描得到一系列的BeanDefinition对象,然后判断这些BeanDefinition是不是也是配置类BeanDefinition(只要存在@Component注解就是配置类,所以基本上扫描出来的都是配置类),如果是则继续解析该配置类,(也有递归),并且会生成对应的ConfigurationClass。

7. 如果配置类上存在@Import注解,那么则判断Import的类的类型:

  • 如果是ImportSelector,那么调用执行selectImports方法得到类名,然后在把这个类当做配置类进行解析,(也是递归);
  • 如果是ImportBeanDefinitionRegistrar,那么则生成一个ImportBeanDefinitionRegistrar实例对象,并添加到配置类对象中(ConfigurationClass)的importBeanDefinitionRegistrars属性中;

8. 如果配置类上存在@ImportResource注解,那么则把导入进来的资源路径存在配置类对象中的importedResources属性中。

9. 如果配置类中存在@Bean的方法,那么则把这些方法封装为BeanMethod对象,并添加到配置类对象中的beanMethods属性中。

10. 如果配置类实现了某些接口,则看这些接口内是否定义了@Bean注解的方法。

11. 如果配置类有父类,则把父类当做配置类进行解析。

12. ScanBean配置类会对应一个ConfigurationClass,同时在解析的过程中也会生成另外的一些ConfigurationClass,接下来就利用reader来进一步解析ConfigurationClass:

  • 如果ConfigurationClass是通过@Import注解导入进来的,则把这个类生成一个BeanDefinition,同时解析这个类上@Scope、@Lazy等注解信息,并注册BeanDefinition;
  • 如果ConfigurationClass中存在一些BeanMethod,也就是定义了一些@Bean,那么则解析这些@Bean,并生成对应的BeanDefinition,并注册;
  • 如果ConfigurationClass中导入了一些资源文件,比如xx.xml,那么则解析这些xx.xml文件,得到并注册BeanDefinition;
  • 如果ConfigurationClass中导入了一些ImportBeanDefinitionRegistrar,那么则执行对应的registerBeanDefinitions进行BeanDefinition的注册。

猜你喜欢

转载自blog.csdn.net/qq_40213907/article/details/120996508