前言

ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口,该类会在AbstractApplicationContext#refresh 中的第5步时进行调用.由于其postProcessBeanDefinitionRegistry 实现过程非常复杂,因此单拿一篇进行分析

解析

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 代码如下:

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

2件事

  1. 根据BeanDefinitionRegistry,生成registryId 加入到registriesPostProcessed中.registriesPostProcessed是为了做去重的判断,当重复对一个BeanDefinitionRegistry进行处理时,则会抛出IllegalStateException.

  2. 调用processConfigBeanDefinitions 进行类的加载.代码如下:

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
    // 1. 获取已经注册的bean名称
    String[] candidateNames = registry.getBeanDefinitionNames(); for (String beanName : candidateNames) {
    BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
    // 1.1. 如果BeanDefinition 中的configurationClass 属性为full 或者lite ,则意味着已经处理过了,直接跳过
    if (logger.isDebugEnabled()) {
    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
    }
    }
    // 1.2. 判断对应bean是否为配置类,如果是,则加入到configCandidates
    else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
    configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    }
    } // Return immediately if no @Configuration classes were found
    // 1.3 如果不存在配置类,则直接return
    if (configCandidates.isEmpty()) {
    return;
    } // Sort by previously determined @Order value, if applicable
    // 2. 对configCandidates 进行 排序,按照@Order 配置的值进行排序
    Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
    @Override
    public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
    int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
    }
    }); // Detect any custom bean name generation strategy supplied through the enclosing application context
    // 3. 如果BeanDefinitionRegistry 是SingletonBeanRegistry 子类的话,由于我们当前传入的是DefaultListableBeanFactory,是
    // SingletonBeanRegistry 的子类。因此会将registry强转为SingletonBeanRegistry
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
    sbr = (SingletonBeanRegistry) registry;
    if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
    // 如果localBeanNameGeneratorSet 等于false 并且SingletonBeanRegistry 中有 id 为 org.springframework.context.annotation.internalConfigurationBeanNameGenerator
    // 的bean .则将componentScanBeanNameGenerator,importBeanNameGenerator 赋值为 该bean.
    BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
    this.componentScanBeanNameGenerator = generator;
    this.importBeanNameGenerator = generator;
    }
    } // Parse each @Configuration class
    // 4. 实例化ConfigurationClassParser 为了解析 各个配置类
    ConfigurationClassParser parser = new ConfigurationClassParser(
    this.metadataReaderFactory, this.problemReporter, this.environment,
    this.resourceLoader, this.componentScanBeanNameGenerator, registry); // 实例化2个set,candidates 用于将之前加入的configCandidates 进行去重
    // alreadyParsed 用于判断是否处理过
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    // 5. 进行解析
    do {
    parser.parse(candidates);
    parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(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);
    alreadyParsed.addAll(configClasses); candidates.clear();
    if (registry.getBeanDefinitionCount() > candidateNames.length) {
    String[] newCandidateNames = registry.getBeanDefinitionNames();
    Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
    Set<String> alreadyParsedClasses = new HashSet<String>();
    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
    // 6.
    if (sbr != null) {
    if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    // 如果SingletonBeanRegistry 不包含org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry
    // 则注册一个,bean 为 ImportRegistry. 一般都会进行注册的
    sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }
    } // 7. 清除缓存
    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
    }

    7件事:

    1. 获取已经注册的bean名称,进行遍历

      1. 如果BeanDefinition 中的configurationClass 属性为full 或者lite ,则意味着已经处理过了,直接跳过
      2. 判断对应bean是否为配置类,如果是,则加入到configCandidates.
      3. 如果不存在配置类,则直接return
    2. 对configCandidates 进行 排序,按照@Order 配置的值进行排序
    3. 如果BeanDefinitionRegistry 是SingletonBeanRegistry 子类的话,由于我们当前传入的是DefaultListableBeanFactory,是 SingletonBeanRegistry 的子类。因此会将registry强转为SingletonBeanRegistry.

      • 如果localBeanNameGeneratorSet 等于false 并且SingletonBeanRegistry 中有 id 为 org.springframework.context.annotation.internalConfigurationBeanNameGenerator的bean .则将componentScanBeanNameGenerator,importBeanNameGenerator 赋值为 该bean.
    4. 实例化ConfigurationClassParser 为了解析各个配置类.实例化2个set,candidates 用于将之前加入的configCandidates 进行去重,alreadyParsed 用于判断是否处理过
    5. 进行解析

      1. 调用ConfigurationClassParser#parse进行解析
      2. 将解析过的配置类加入到configClasses,并将configClasses去重已经处理过的,以防止重复加载
      3. 如果reader为null,则实例化ConfigurationClassBeanDefinitionReader
      4. 调用ConfigurationClassBeanDefinitionReader#loadBeanDefinitions 进行加载,并加入到alreadyParsed中,用于去重
      5. 将candidates进行清空,如果registry中注册的bean的数量 大于 之前获得的数量,则意味着在解析过程中又新加入了很多,那么就需要对其进行解析
    6. 如果SingletonBeanRegistry 不包含org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry,则注册一个,bean 为 ImportRegistry. 一般都会进行注册的
    7. 清除缓存

    1.2 判断对应bean是否为配置类 调用的是ConfigurationClassUtils#checkConfigurationClassCandidate.代码如下:

    public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    // 1. 获取类名,如果类名不存在则返回false
    String className = beanDef.getBeanClassName();
    if (className == null) {
    return false;
    } // 2. 获得AnnotationMetadata
    AnnotationMetadata metadata;
    if (beanDef instanceof AnnotatedBeanDefinition &&
    className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
    // Can reuse the pre-parsed metadata from the given BeanDefinition...
    // 2.1 如果BeanDefinition 是 AnnotatedBeanDefinition的实例,并且className 和 BeanDefinition中 的元数据 的类名相同
    // 则直接从BeanDefinition 获得Metadata
    metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
    }
    else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
    // Check already loaded Class if present...
    // since we possibly can't even load the class file for this Class.
    // 2.2 如果BeanDefinition 是 AnnotatedBeanDefinition的实例,并且beanDef 有 beanClass 属性存在
    // 则实例化StandardAnnotationMetadata
    Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
    metadata = new StandardAnnotationMetadata(beanClass, true);
    }
    else {
    try {
    // 2.3 否则 通过MetadataReaderFactory 中的MetadataReader 进行读取
    MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
    metadata = metadataReader.getAnnotationMetadata();
    }
    catch (IOException ex) {
    if (logger.isDebugEnabled()) {
    logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
    }
    return false;
    }
    } // 3.
    if (isFullConfigurationCandidate(metadata)) {
    // 3.1 如果存在Configuration 注解,则为BeanDefinition 设置configurationClass属性为full
    beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    else if (isLiteConfigurationCandidate(metadata)) {
    // 3.2 如果AnnotationMetadata 中有Component,ComponentScan,Import,ImportResource 注解中的任意一个,或者存在 被@bean 注解的方法,则返回true.
    // 则设置configurationClass属性为lite
    beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
    // 3.3 返回false
    return false;
    } // It's a full or lite configuration candidate... Let's determine the order value, if any.
    // 4. 如果该类被@Order所注解,则设置order属性为@Order的值
    Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
    if (orderAttributes != null) {
    beanDef.setAttribute(ORDER_ATTRIBUTE, orderAttributes.get(AnnotationUtils.VALUE));
    } return true;
    }

    5件事:

    1. 获取类名,如果类名不存在则返回false
    2. 获得AnnotationMetadata

      1. 如果BeanDefinition 是 AnnotatedBeanDefinition的实例,并且className 和 BeanDefinition中的元数据的类名相同,则直接从BeanDefinition 获得Metadata
      2. 如果BeanDefinition 是 AnnotatedBeanDefinition的实例,并且beanDef 有 beanClass属性存在,则实例化StandardAnnotationMetadata
      3. 否则 通过MetadataReaderFactory 中的MetadataReader 进行读取
    3. 进行判断

      1. 如果存在Configuration 注解,则为BeanDefinition 设置configurationClass属性为full.
      2. 如果AnnotationMetadata 中有Component,ComponentScan,Import,ImportResource 注解中的任意一个,或者存在 被@bean 注解的方法,则返回true.
      3. 否则,返回false
    4. 如果该类被@Order所注解,则设置order属性为@Order的值
    5. 返回true.

    5.1 调用的是ConfigurationClassParser#parse,代码如下:

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
    this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>(); for (BeanDefinitionHolder holder : configCandidates) {
    BeanDefinition bd = holder.getBeanDefinition();
    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);
    }
    } processDeferredImportSelectors();
    }

    3件事

    1. 实例化deferredImportSelectors
    2. 遍历configCandidates ,进行处理.根据BeanDefinition 的类型 做不同的处理,一般都会调用ConfigurationClassParser#parse 进行解析
    3. 处理ImportSelect

    其中第2步 执行的代码如下:

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

    最终调用

    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
    // 1. 判断是否应该被跳过
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
    return;
    } // 2. 处理Imported 的情况
    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);
    for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
    if (configClass.equals(it.next())) {
    it.remove();
    }
    }
    }
    } // Recursively process the configuration class and its superclass hierarchy.
    SourceClass sourceClass = asSourceClass(configClass);
    do {
    // 3. 递归调用进行解析
    sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
    while (sourceClass != null); // 4. 添加到configurationClasses中
    this.configurationClasses.put(configClass, configClass);
    }

    4件事:

    1. 判断是否应该被跳过.通过调用ConditionEvaluator#shouldSkip实现的,代码如下:

      public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
      // 1. 如果这个类没有被@Conditional注解所修饰,不会skip
      if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
      return false;
      } // 2. 如果参数中沒有设置条件注解的生效阶段
      if (phase == null) {
      // 是配置类的话直接使用PARSE_CONFIGURATION阶段
      if (metadata instanceof AnnotationMetadata &&
      ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
      return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
      }
      // 否则使用REGISTER_BEAN阶段
      return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
      } List<Condition> conditions = new ArrayList<Condition>(); // 要解析的配置类的条件集合
      // 3. 获取配置类的条件注解得到条件数据,并添加到集合中
      for (String[] conditionClasses : getConditionClasses(metadata)) {
      for (String conditionClass : conditionClasses) {
      Condition condition = getCondition(conditionClass, this.context.getClassLoader());
      conditions.add(condition);
      }
      } AnnotationAwareOrderComparator.sort(conditions); // 4. 遍历conditions,进行判断
      for (Condition condition : conditions) {
      ConfigurationPhase requiredPhase = null;
      if (condition instanceof ConfigurationCondition) {
      requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
      }
      if (requiredPhase == null || requiredPhase == phase) {
      // 阶段不满足条件的话,返回true并跳过这个bean的解析
      if (!condition.matches(this.context, metadata)) {
      return true;
      }
      }
      } return false;
      }

      4件事

      1. 如果这个类没有被@Conditional注解所修饰,不会skip,返回false
      2. 如果参数中沒有设置条件注解的生效阶段

        1. 是配置类的话直接使用PARSE_CONFIGURATION阶段,递归调用shouldSkip 进行判断
        2. 否则使用REGISTER_BEAN阶段,递归调用shouldSkip 进行判断
      3. 获取配置类的条件注解得到条件数据,并添加到集合中
      4. 遍历conditions,进行判断,如果阶段不满足条件的话,返回true并跳过这个bean的解析
    2. 处理Imported 的情况
    3. 递归调用进行解析
    4. 添加到configurationClasses中

    其中第三步,代码如下:

    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
    throws IOException { // 1. Recursively process any member (nested) classes first 处理内部类
    processMemberClasses(configClass, sourceClass); // 2. Process any @PropertySource annotations 处理@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.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
    "]. Reason: Environment must implement ConfigurableEnvironment");
    }
    } // 3. 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
    // 3.1 进行扫描
    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
    // 3.2 依次遍历扫描的配置类进行解析
    for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
    if (ConfigurationClassUtils.checkConfigurationClassCandidate(
    holder.getBeanDefinition(), this.metadataReaderFactory)) {
    parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
    }
    }
    }
    } // 4. Process any @Import annotations 处理@Import
    processImports(configClass, sourceClass, getImports(sourceClass), true); // 5. Process any @ImportResource annotations
    if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
    AnnotationAttributes importResource =
    AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    String[] resources = importResource.getStringArray("locations");
    // 遍历配置的locations,加入到configClass 中的ImportedResource
    Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
    for (String resource : resources) {
    String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
    configClass.addImportedResource(resolvedResource, readerClass);
    }
    } // 6. Process individual @Bean methods
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    // 遍历@Bean注释的方法,添加到configClass
    for (MethodMetadata methodMetadata : beanMethods) {
    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    } // 7. Process default methods on interfaces
    processInterfaces(configClass, sourceClass); // 8. Process superclass, if any 如果有父类的话,则返回父类进行进一步的解析
    if (sourceClass.getMetadata().hasSuperClass()) {
    String superclass = sourceClass.getMetadata().getSuperClassName();
    if (!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;
    }

    8件事

    1. 处理内部类.代码如下:

      private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
      // 1. 遍历class中的内部类
      for (SourceClass memberClass : sourceClass.getMemberClasses()) {
      if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
      !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
      // 2. 如果该内部类是一个配置类,并且该内部类的类名和configClass的类名不相同
      if (this.importStack.contains(configClass)) {
      // 2.1 如果importStack 包含该configClass的化,则意味发生了循环依赖,则会抛出BeanDefinitionParsingException 异常
      this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
      }
      else {
      // 2.2 否则加入到importStack,调用processConfigurationClass 进行解析
      this.importStack.push(configClass);
      try {
      processConfigurationClass(memberClass.asConfigClass(configClass));
      }
      finally {
      this.importStack.pop();
      }
      }
      }
      }
      }

      2件事:

      1. 遍历class中的内部类
      2. 如果该内部类是一个配置类,并且该内部类的类名和configClass的类名不相同

        1. 如果importStack 包含该configClass的化,则意味发生了循环依赖,则会抛出BeanDefinitionParsingException 异常
        2. 否则加入到importStack,调用processConfigurationClass 进行解析,最后在弹出该configClass.
    2. 处理@PropertySource.通过遍历该类中的@PropertySource的注解,如果该类中的environment是ConfigurableEnvironment 子类的话,则调用processPropertySource进行处理.否则打印警告日志.一般都是ConfigurableEnvironment的子类.代码如下:

      private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
      // 1. 解析name、encoding值
      String name = propertySource.getString("name");
      if (!StringUtils.hasLength(name)) {
      name = null;
      }
      String encoding = propertySource.getString("encoding");
      if (!StringUtils.hasLength(encoding)) {
      encoding = null;
      }
      // 2. 解析value(数组)以及ignoreResourceNotFound值
      String[] locations = propertySource.getStringArray("value");
      Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
      boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound"); // 3. 解析factory,如果该值没有配置,默认为PropertySourceFactory则直接实例化DefaultPropertySourceFactory类,否则开始实例化自定义的类
      Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
      PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
      DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass)); for (String location : locations) {
      try {
      // 4.1 对location进行SPEL表达式的解析。比如当前的配置环境中有一个属性为app=shareniu,我们配置的location为${app}最终值为shareniu。通过这里的处理逻辑可以知道location支持多环境的切换以及表达式的配置
      String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
      // 4.2 使用资源加载器resourceLoader将resolvedLocation抽象为Resource
      Resource resource = this.resourceLoader.getResource(resolvedLocation);
      // 4.3 调用addPropertySource属性进行处理。将指定的资源处理之后,添加到当前springboot运行的环境中
      addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
      }
      catch (IllegalArgumentException ex) {
      // 5. 如果上述的任意步骤报错,则开始查找ignoreResourceNotFound的值,如果该值为treu,则忽略异常,否则直接报错
      // Placeholders not resolvable
      if (ignoreResourceNotFound) {
      if (logger.isInfoEnabled()) {
      logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
      }
      }
      else {
      throw ex;
      }
      }
      catch (IOException ex) {
      // Resource not found when trying to open it
      if (ignoreResourceNotFound &&
      (ex instanceof FileNotFoundException || ex instanceof UnknownHostException)) {
      if (logger.isInfoEnabled()) {
      logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
      }
      }
      else {
      throw ex;
      }
      }
      }
      }

      5件事:

      1. 解析name、encoding值
      2. 解析value(数组)以及ignoreResourceNotFound值
      3. 解析factory,如果该值没有配置,默认为PropertySourceFactory则直接实例化DefaultPropertySourceFactory类,否则开始实例化自定义的类
      4. 遍历配置的locations进行处理

        1. 对location进行SPEL表达式的解析。比如当前的配置环境中有一个属性为app=shareniu,我们配置的location为${app}最终值为shareniu。通过这里的处理逻辑可以知道location支持多环境的切换以及表达式的配置
        2. 使用资源加载器resourceLoader将resolvedLocation抽象为Resource
        3. 调用addPropertySource属性进行处理。将指定的资源处理之后,添加到当前springboot运行的环境中

      5.如果上述的任意步骤报错,则开始查找ignoreResourceNotFound的值,如果该值为treu,则忽略异常,否则直接报错

    3. 处理@ComponentScan,通过遍历该类上的@ComponentScan 注解,并且通过ConditionEvaluator#shouldSkip判断后

      1. 依次通过ComponentScanAnnotationParser#parse进行扫描。最终调用ClassPathBeanDefinitionScanner#doScan.代码如下:

        protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
        for (String basePackage : basePackages) {
        // 扫描basePackage路径下的java文件
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
        // 解析scope属性
        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) {
        // 如果是AnnotatedBeanDefinition类型,则检查常用注解:如lazy等
        AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
        }
        // 检查当前bean是否已经注册
        if (checkCandidate(beanName, candidate)) {
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
        // 如果当前bean是用于生成代理的bean那么需要进一步处理
        definitionHolder =
        AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        beanDefinitions.add(definitionHolder);
        registerBeanDefinition(definitionHolder, this.registry);
        }
        }
        }
        return beanDefinitions;
        }
        1. 遍历basePackages,通过findCandidateComponents方法扫描basePackage路径下的java文件
        2. 如果扫描到文件的话,则遍历之.

          1. 解析scope属性
          2. 生成beanName.
          3. 如果该 BeanDefinition 是AbstractBeanDefinition 的子类的话,则调用postProcessBeanDefinition为其设置默认值.代码如下:

                protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
            beanDefinition.applyDefaults(this.beanDefinitionDefaults);
            if (this.autowireCandidatePatterns != null) {
            beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
            }
            }
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            1. 为其设置默认值.

                  public void applyDefaults(BeanDefinitionDefaults defaults) {
              setLazyInit(defaults.isLazyInit());//false
              setAutowireMode(defaults.getAutowireMode());//AUTOWIRE_NO
              setDependencyCheck(defaults.getDependencyCheck());//DEPENDENCY_CHECK_NONE
              setInitMethodName(defaults.getInitMethodName());// null
              setEnforceInitMethod(false);
              setDestroyMethodName(defaults.getDestroyMethodName());//null
              setEnforceDestroyMethod(false);
              }
            2. 如果autowireCandidatePatterns 不等于null的话,则设置AutowireCandidate.
          4. 如果该BeanDefinition是AnnotatedBeanDefinition的子类,则调用AnnotationConfigUtils#processCommonDefinitionAnnotations,检查常用注解:如lazy等
          5. 检查当前bean是否已经注册,如果没有注册的话,则

            1. 生成BeanDefinitionHolder
            2. 如果当前bean是用于生成代理的bean那么需要进一步处理,代码如下:

                  static BeanDefinitionHolder applyScopedProxyMode(
              ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
              ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
              if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
              return definition;
              }
              boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
              return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
              }

              由于一般ScopedProxyMode都是NO,因此也就不会生成代理

            3. 添加到beanDefinitions中
            4. 向BeanDefinitionRegistry进行注册
      2. 依次遍历扫描的配置类进行递归解析.最终又会调用ConfigurationClassParser#processConfigurationClass
    4. 处理@Import.代码如下:

          private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
      Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException { // 1. 如果importCandidates为空,则直接return
      if (importCandidates.isEmpty()) {
      return;
      } // 2. 进行循环依赖的检查
      if (checkForCircularImports && isChainedImportOnStack(configClass)) {
      this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
      }
      else {
      this.importStack.push(configClass);
      try {
      // 3. 如果不存在循环依赖,则依次遍历处理之
      for (SourceClass candidate : importCandidates) {
      if (candidate.isAssignable(ImportSelector.class)) {
      // 3.1 如果是ImportSelector的子类
      // Candidate class is an ImportSelector -> delegate to it to determine imports
      Class<?> candidateClass = candidate.loadClass();
      // 则实例化后,调用ParserStrategyUtils#invokeAwareMethods
      ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
      ParserStrategyUtils.invokeAwareMethods(
      selector, this.environment, this.resourceLoader, this.registry);
      if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
      // 3.2 如果当前类是DeferredImportSelector 的实现,则加入到deferredImportSelectors
      this.deferredImportSelectors.add(
      new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
      }
      else {
      // 3.3 如果不是,则调用processImports 进行处理.
      String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
      Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
      processImports(configClass, currentSourceClass, importSourceClasses, false);
      }
      }
      else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
      // Candidate class is an ImportBeanDefinitionRegistrar ->
      // delegate to it to register additional bean definitions
      // 如果是ImportBeanDefinitionRegistrar的子类,则实例化后,调用ParserStrategyUtils#invokeAwareMethods,
      // 添加到configClass中
      Class<?> candidateClass = candidate.loadClass();
      ImportBeanDefinitionRegistrar registrar =
      BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
      ParserStrategyUtils.invokeAwareMethods(
      registrar, this.environment, this.resourceLoader, this.registry);
      configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
      }
      else {
      // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
      // process it as an @Configuration class
      // 3. 否则,加入到importStack后调用processConfigurationClass 进行处理.
      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();
      }
      }
      }
      1. 如果@Import注解不存在的话,则直接return.
      2. 进行循环依赖的检查,如果存在循环依赖的话,则直接抛出异常
      3. 加入importStack中,用于循环依赖的检查,依次遍历 @Import

        1. 如果是ImportSelector的子类,则实例化后,调用ParserStrategyUtils#invokeAwareMethods.

          1. 如果当前类是DeferredImportSelector 的实现,则加入到deferredImportSelectors
          2. 如果不是,则调用processImports 进行处理.
        2. 如果是ImportBeanDefinitionRegistrar的子类,则实例化后,调用ParserStrategyUtils#invokeAwareMethods,添加到configClass中

        3. 否则,加入到importStack后调用processConfigurationClass 进行处理.
      4. 最后,从importStack栈顶元素.

      其中ParserStrategyUtils#invokeAwareMethods,代码如下:

          public static void invokeAwareMethods(Object parserStrategyBean, Environment environment,
      ResourceLoader resourceLoader, BeanDefinitionRegistry registry) { if (parserStrategyBean instanceof Aware) {
      if (parserStrategyBean instanceof BeanClassLoaderAware) {
      ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
      ((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
      ((BeanClassLoaderAware) parserStrategyBean).setBeanClassLoader(classLoader);
      }
      if (parserStrategyBean instanceof BeanFactoryAware && registry instanceof BeanFactory) {
      ((BeanFactoryAware) parserStrategyBean).setBeanFactory((BeanFactory) registry);
      }
      if (parserStrategyBean instanceof EnvironmentAware) {
      ((EnvironmentAware) parserStrategyBean).setEnvironment(environment);
      }
      if (parserStrategyBean instanceof ResourceLoaderAware) {
      ((ResourceLoaderAware) parserStrategyBean).setResourceLoader(resourceLoader);
      }
      }
      }
      1. 如果parserStrategyBean 是Aware 的子类

        1. 如果parserStrategyBean是BeanClassLoaderAware的子类,则为其注入ClassLoader
        2. 如果parserStrategyBean是BeanFactoryAware的子类并且registry是BeanFactory的子类,则为其注入BeanFactory
        3. 如果parserStrategyBean是EnvironmentAware的子类,则为其注入Environment
        4. 如果parserStrategyBean是ResourceLoaderAware的子类,则为其注入ResourceLoader
      2. 否则不进行处理.
    5. 处理@ImportResource,通过获得其@ImportResource,获得locations值后, 遍历配置的locations,加入到configClass 中的ImportedResource.
    6. 处理被@Bean注解的方法,遍历@Bean注释的方法,添加到configClass中的BeanMethod
    7. 处理接口中被@Bean注解默认方法,代码如下:

      private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
      // 1. 遍历sourceClass 的接口
      for (SourceClass ifc : sourceClass.getInterfaces()) {
      // 2. 获得被@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...
      // 3. 如果不是抽象方法的话,则加入到configClass的BeanMethod
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
      }
      }
      // 4. 递归处理
      processInterfaces(configClass, ifc);
      }
      }
      1. 遍历sourceClass 的接口
      2. 获得被@bean注释的方法
      3. 如果不是抽象方法的话,则加入到configClass的BeanMethod
      4. 递归调用processInterfaces,看其父接口中是否存在被@bean注解的方法,直到父接口不存在.
    8. 如果有父类的话,则返回父类进行进一步的解析,否则返回null

    5.4 调用的是ConfigurationClassBeanDefinitionReader#loadBeanDefinitions,代码如下:

        public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    // 1. 实例化TrackedConditionEvaluator
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    // 2. 遍历configurationModel,依次调用loadBeanDefinitionsForConfigurationClass
    for (ConfigurationClass configClass : configurationModel) {
    loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
    }

    2件事:

    1. 实例化TrackedConditionEvaluator
    2. 遍历configurationModel,依次调用loadBeanDefinitionsForConfigurationClass进行加载.代码如下:

      private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
      TrackedConditionEvaluator trackedConditionEvaluator) { // 1. 使用条件注解判断是否需要跳过这个配置类
      if (trackedConditionEvaluator.shouldSkip(configClass)) {
      String beanName = configClass.getBeanName();
      // 1.1 跳过配置类的话在Spring容器中移除bean的注册
      if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
      this.registry.removeBeanDefinition(beanName);
      }
      // 1.2 从importRegistry 进行删除.
      this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
      return;
      } if (configClass.isImported()) {
      // 2. 如果自身是被@Import注释所import的,注册自己
      registerBeanDefinitionForImportedConfigurationClass(configClass);
      }
      // 3. 遍历BeanMethods,依次对其进行注册.
      for (BeanMethod beanMethod : configClass.getBeanMethods()) {
      loadBeanDefinitionsForBeanMethod(beanMethod);
      }
      // 4.注册@ImportResource注解注释的资源文件中的bean
      loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
      // 5. 注册@Import注解中的ImportBeanDefinitionRegistrar接口的registerBeanDefinitions
      loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
      }

      5件事:

      1. 使用条件注解判断是否需要跳过这个配置类,如果需要跳过的话,则Spring容器中移除该bean.并且从importRegistry删除.然后直接return.否则执行第2步.
      2. 如果自身是被@Import注解所import的,则调用registerBeanDefinitionForImportedConfigurationClass进行注册.代码如下:

        private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
        // 1. 根据configClass中配置的AnnotationMetadata 实例化AnnotatedGenericBeanDefinition
        AnnotationMetadata metadata = configClass.getMetadata();
        AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
        // 2 进行属性的设置
        // 2.1 解析该configClass的Scope
        ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
        configBeanDef.setScope(scopeMetadata.getScopeName());
        // 2.2 生成bean的id
        String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
        // 2.3 设置bean的一些属性,如LazyInit,Primary等
        AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
        // 3. 生成BeanDefinitionHolder,并对其尝试进行代理,最后向registry进行注册
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
        configClass.setBeanName(configBeanName);
        if (logger.isDebugEnabled()) {
        logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
        }
        }

        3件事

        1. 根据configClass中配置的AnnotationMetadata 实例化AnnotatedGenericBeanDefinition
        2. 进行属性的设置

          1. 解析该configClass的Scope
          2. 生成bean的id
          3. 设置bean的一些属性,如LazyInit,Primary等
          4. 生成BeanDefinitionHolder,并对其尝试进行代理,最后向registry进行注册
      3. 遍历BeanMethods,依次对其调用loadBeanDefinitionsForBeanMethod进行注册.代码如下:

        private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
        // 1. 获得声明该BeanMethod的ConfigurationClass
        ConfigurationClass configClass = beanMethod.getConfigurationClass();
        // 获得BeanMethod的MethodMetadata和methodName
        MethodMetadata metadata = beanMethod.getMetadata();
        String methodName = metadata.getMethodName();
        // Do we need to mark the bean as skipped by its condition?
        // 2. 进行判断,是否应该跳过处理
        // 2.1 如果ConditionEvaluator#shouldSkip返回true,则添加到configClass的skippedBeanMethods中,return
        if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
        configClass.skippedBeanMethods.add(methodName);
        return;
        }
        // 2.2 如果configClass的skippedBeanMethods包含该methodName的话,不进行处理,
        if (configClass.skippedBeanMethods.contains(methodName)) {
        return;
        }
        // Consider name and any aliases
        // 3. 从@Bean 中获得配置的names,如果names不为空的话,则第一个为bean的id,否则该方法名字作为bean的id
        AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
        List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
        String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
        // Register aliases even when overridden
        // 4. 将names 当做别名进行注册
        for (String alias : names) {
        this.registry.registerAlias(beanName, alias);
        }
        // Has this effectively been overridden before (e.g. via XML)?
        // 5. 如果存在重复定义的情况,则直接return
        if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
        return;
        }
        // 6. 实例化ConfigurationClassBeanDefinition
        ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
        beanDef.setResource(configClass.getResource());
        beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
        if (metadata.isStatic()) {
        // 6.1 如果该方法是静态的,则将methodName设置为工厂方法
        // static @Bean method
        beanDef.setBeanClassName(configClass.getMetadata().getClassName());
        beanDef.setFactoryMethodName(methodName);
        }
        else {
        // instance @Bean method
        // 6.2 如果是实例方法的话,则将configClass的BeanName设置为FactoryBeanName,methodName设置为UniqueFactoryMethodName
        beanDef.setFactoryBeanName(configClass.getBeanName());
        beanDef.setUniqueFactoryMethodName(methodName);
        }
        // 6.3 设置AutowireMode 为 构造器注入
        beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        // 设置skipRequiredCheck属性为true.
        beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
        // 6.4 进行一些常用的属性设置
        AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
        Autowire autowire = bean.getEnum("autowire");
        if (autowire.isAutowire()) {
        beanDef.setAutowireMode(autowire.value());
        }
        String initMethodName = bean.getString("initMethod");
        if (StringUtils.hasText(initMethodName)) {
        // 设置 InitMethod
        beanDef.setInitMethodName(initMethodName);
        }
        String destroyMethodName = bean.getString("destroyMethod");
        if (destroyMethodName != null) {
        // 设置 DestroyMethod
        beanDef.setDestroyMethodName(destroyMethodName);
        }
        // Consider scoping
        // 6.5 设置ScopedProxyMode
        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
        // 6.6 如果ScopedProxyMode 不等于NO,则生成代理
        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.isDebugEnabled()) {
        logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
        configClass.getMetadata().getClassName(), beanName));
        }
        // 7. 进行注册
        this.registry.registerBeanDefinition(beanName, beanDefToRegister);
        }

        7件事:

        1. 获得声明该BeanMethod的ConfigurationClass,获得BeanMethod的MethodMetadata和methodName
        2. 进行判断,是否应该跳过处理

          1. 如果ConditionEvaluator#shouldSkip返回true,则添加到configClass的skippedBeanMethods中,return
          2. 如果configClass的skippedBeanMethods包含该methodName的话,不进行处理,
        3. 从@Bean 中获得配置的names,如果names不为空的话,则第一个为bean的id,否则该方法名字作为bean的id
        4. 将names 当做别名进行注册
        5. 如果存在重复定义的情况,则直接return
        6. 实例化ConfigurationClassBeanDefinition

          1. 如果该方法是静态的,则将methodName设置为工厂方法
          2. 否则如果是实例方法的话,则将configClass的BeanName设置为FactoryBeanName,methodName设置为UniqueFactoryMethodName
          3. 设置AutowireMode 为 构造器注入,设置skipRequiredCheck属性为true.
          4. 进行一些常用的属性设置
          5. 设置 InitMethod
          6. 设置 DestroyMethod
          7. 设置ScopedProxyMode,如果ScopedProxyMode 不等于NO,则生成代理
        7. 进行注册
      4. 注册@ImportResource注解注释的资源文件中的bean.代码如下:

        private void loadBeanDefinitionsFromImportedResources(
        Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
        Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<Class<?>, BeanDefinitionReader>();
        // 1. 遍历importedResources
        for (Map.Entry<String, Class<? extends BeanDefinitionReader>> entry : importedResources.entrySet()) {
        String resource = entry.getKey();
        Class<? extends BeanDefinitionReader> readerClass = entry.getValue(); // Default reader selection necessary?
        // 2. 选择BeanDefinitionReader
        if (BeanDefinitionReader.class == readerClass) {
        if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
        // When clearly asking for Groovy, that's what they'll get...
        // 2.1 如果是.groovy,则为GroovyBeanDefinitionReader
        readerClass = GroovyBeanDefinitionReader.class;
        }
        else {
        // Primarily ".xml" files but for any other extension as well
        // 2.2 否则为XmlBeanDefinitionReader,一般都是XmlBeanDefinitionReader
        readerClass = XmlBeanDefinitionReader.class;
        }
        } // 3. 尝试从readerInstanceCache中获取对应的BeanDefinitionReader
        BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
        if (reader == null) {// 如果不存在,则实例化一个
        try {
        // Instantiate the specified BeanDefinitionReader
        reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
        // Delegate the current ResourceLoader to it if possible
        if (reader instanceof AbstractBeanDefinitionReader) {
        // 如果reader是AbstractBeanDefinitionReader的子类的话,这个肯定是...
        AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
        abdr.setResourceLoader(this.resourceLoader);
        abdr.setEnvironment(this.environment);
        }
        // 然后放入readerInstanceCache,以防止重复实例化.
        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);}}

        3件事:

        1. 遍历importedResources
        2. 选择BeanDefinitionReader

          1. 如果是.groovy结尾的话,则为GroovyBeanDefinitionReader
          2. 否则为XmlBeanDefinitionReader,一般都是XmlBeanDefinitionReader
        3. 尝试从readerInstanceCache中获取对应的BeanDefinitionReader,如果不存在,则实例化一个,然后放入到readerInstanceCache缓存中
        4. 调用BeanDefinitionReader#loadBeanDefinitions进行加载.

        由于一般情况下都是XmlBeanDefinitionReader,最终会调用XmlBeanDefinitionReader#loadBeanDefinitions进行加载,这部分属于spring加载xml部分了,碍于篇幅,这里就不在展开了,后续会有文章进行分析的.

      5. 注册@Import注解中的ImportBeanDefinitionRegistrar接口的registerBeanDefinitions.代码如下:

        private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
        for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> entry : registrars.entrySet()) {
        entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
        }
        }

        只是简单的进行注册.

    至此关于bean的加载我们就分析完了.

参考链接

spring boot实战(第十篇)Spring boot Bean加载源码分析

原文地址;https://blog.csdn.net/qq_26000415/article/details/78917682

spring boot 源码解析11-ConfigurationClassPostProcessor类加载解析的更多相关文章

  1. 曹工说Spring Boot源码(11)-- context:component-scan,你真的会用吗(这次来说说它的奇技淫巧)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  2. 曹工说Spring Boot源码(15)-- Spring从xml文件里到底得到了什么(context:load-time-weaver 完整解析)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  3. 曹工说Spring Boot源码(30)-- ConfigurationClassPostProcessor 实在太硬核了,为了了解它,我可能debug了快一天

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  4. 曹工说Spring Boot源码(12)-- Spring解析xml文件,到底从中得到了什么(context:component-scan完整解析)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  5. 曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析【上】)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  6. 曹工说Spring Boot源码(17)-- Spring从xml文件里到底得到了什么(aop:config完整解析【中】)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  7. 曹工说Spring Boot源码(18)-- Spring AOP源码分析三部曲,终于快讲完了 (aop:config完整解析【下】)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  8. 曹工说Spring Boot源码(19)-- Spring 带给我们的工具利器,创建代理不用愁(ProxyFactory)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  9. 曹工说Spring Boot源码(22)-- 你说我Spring Aop依赖AspectJ,我依赖它什么了

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  10. 曹工说Spring Boot源码(28)-- Spring的component-scan机制,让你自己来进行简单实现,怎么办

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

随机推荐

  1. PyCharm中批量查找及替换

    选中需要操作的字符 Ctrl + R 替换 Ctrl + Shift + F 全局查找 Ctrl + Shift + R 全局替换 源自: PyCharm中批量查找及替换 - Ella_Wu - 博客 ...

  2. Linux QtCreator 创建工程

    这一天天的,都快成废物了, 每天忙得要死, 各种乱七八糟杂事,连点学习的时间都没有了, 这才一年不碰Linux,创建工程都不会了, Ubuntu 1N.N.N + QtCreator 创建工程 不安装 ...

  3. Java Annotation试用

    Java的很多特性了解的差不多了,比如多线程,io,集合类诸如此类的,但是都没做总结,今天恰好用了Annotation,所以就稍微总结下吧. 要用Annotation首先要搞懂元注解 元注解的作用就是 ...

  4. 2019-8-2-WPF-依赖属性绑定不上调试方法

    title author date CreateTime categories WPF 依赖属性绑定不上调试方法 lindexi 2019-08-02 19:56:32 +0800 2019-8-2 ...

  5. telnet- Linux必学的60个命令

    1.作用 telnet表示开启终端机阶段作业,并登入远端主机.telnet是一个Linux命令,同时也是一个协议(远程登陆协议). 2.格式 telnet [-8acdEfFKLrx][-b][-e] ...

  6. [转]Git 常用命令详解

    史上最浅显易懂的Git教程 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/ ht ...

  7. LoadRunner内部结构(1)

    LoadRunner内部结构(1) 根据http://www.wilsonmar.com/1loadrun.htm  翻译: LoadRunner内部结构 1,            被测系统是由驱动 ...

  8. eval()方法与str()方法

    eval()方法与str()方法 #_author:Administrator#date:2019/10/31 a={ 'q':{'xxx':3456}}#将一个字典转换成一个字符串a=str(a)p ...

  9. UOJ450 复读机

    题意:n个位置,k种颜色.求有多少种方案使得每种颜色恰出现d的倍数次. 解:d=1就快速幂,n,k很小就DP,记得乘组合数来分配位置. d = 2 / 3的时候,考虑生成函数. f(x) = ∑[d ...

  10. 使用UUID和int自增主键的区别

    知其然,知其所以然.在看到生成UUID的代码,后带给我的百度结合自己的经验再写下来的区别 一.UUID做主键: 优点: .保证数据在表和库都是独立的,有利于后续的分库 .合并表的时候主键不会重复 .有 ...