private void processImport(
     ConfigurationClass configClass, String[] classesToImport, boolean checkForCircularImports)
     throws IOException {
   if (checkForCircularImports && this.importStack.contains(configClass)) {
     this.problemReporter.error(
         new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
   } else {
     this.importStack.push(configClass);
     AnnotationMetadata importingClassMetadata = configClass.getMetadata();
     for (String candidate : classesToImport) {
       MetadataReader reader = this.metadataReaderFactory.getMetadataReader(candidate);
       if (new AssignableTypeFilter(ImportSelector.class).match(reader, metadataReaderFactory)) {
         // the candidate class is an ImportSelector -> delegate to it to determine imports
         try {
           ImportSelector selector =
               BeanUtils.instantiateClass(Class.forName(candidate), ImportSelector.class);
           ImportSelectorContext context =
               new ImportSelectorContext(importingClassMetadata, this.registry);
           processImport(configClass, selector.selectImports(context), false);
         } catch (ClassNotFoundException ex) {
           throw new IllegalStateException(ex);
         }
       } else {
         // the candidate class not an ImportSelector -> process it as a @Configuration class
         this.importStack.registerImport(importingClassMetadata.getClassName(), candidate);
         processConfigurationClass(new ConfigurationClass(reader, null));
       }
     }
     this.importStack.pop();
   }
 }
  private void processImports(
      ConfigurationClass configClass,
      SourceClass currentSourceClass,
      Collection<SourceClass> importCandidates,
      boolean checkForCircularImports)
      throws IOException {

    if (importCandidates.isEmpty()) {
      return;
    }

    if (checkForCircularImports && this.importStack.contains(configClass)) {
      this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
    } else {
      this.importStack.push(configClass);
      try {
        for (SourceClass candidate : importCandidates) {
          if (candidate.isAssignable(ImportSelector.class)) {
            // Candidate class is an ImportSelector -> delegate to it to determine imports
            Class<?> candidateClass = candidate.loadClass();
            ImportSelector selector =
                BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
            invokeAwareMethods(selector);
            if (this.deferredImportSelectors != null
                && selector instanceof DeferredImportSelector) {
              this.deferredImportSelectors.add(
                  new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
            } else {
              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
            Class<?> candidateClass = candidate.loadClass();
            ImportBeanDefinitionRegistrar registrar =
                BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
            invokeAwareMethods(registrar);
            configClass.addImportBeanDefinitionRegistrar(
                registrar, currentSourceClass.getMetadata());
          } else {
            // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
            // process it as an @Configuration class
            this.importStack.registerImport(
                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
            processConfigurationClass(candidate.asConfigClass(configClass));
          }
        }
      } catch (BeanDefinitionStoreException ex) {
        throw ex;
      } catch (Exception ex) {
        throw new BeanDefinitionStoreException(
            "Failed to process import candidates for configuration class ["
                + configClass.getMetadata().getClassName()
                + "]",
            ex);
      } finally {
        this.importStack.pop();
      }
    }
  }