protected void doProcessConfigurationClass( ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException { // recursively process any member (nested) classes first for (String memberClassName : metadata.getMemberClassNames()) { MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName); AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata(); if (isConfigurationCandidate(memberClassMetadata)) { processConfigurationClass(new ConfigurationClass(reader, null)); } } // process any @PropertySource annotations Map<String, Object> propertySourceAttributes = metadata.getAnnotationAttributes( org.springframework.context.annotation.PropertySource.class.getName()); if (propertySourceAttributes != null) { String name = (String) propertySourceAttributes.get("name"); String[] locations = (String[]) propertySourceAttributes.get("value"); ClassLoader classLoader = this.resourceLoader.getClassLoader(); for (String location : locations) { location = this.environment.resolveRequiredPlaceholders(location); ResourcePropertySource ps = StringUtils.hasText(name) ? new ResourcePropertySource(name, location, classLoader) : new ResourcePropertySource(location, classLoader); this.propertySources.push(ps); } } // process any @ComponentScan annotions Map<String, Object> componentScanAttributes = metadata.getAnnotationAttributes(ComponentScan.class.getName()); if (componentScanAttributes != null) { // the config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScanAttributes); // check the set of scanned definitions for any further config classes and parse recursively // if necessary for (BeanDefinitionHolder holder : scannedBeanDefinitions) { if (ConfigurationClassUtils.checkConfigurationClassCandidate( holder.getBeanDefinition(), metadataReaderFactory)) { try { this.parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName()); } catch (ConflictingBeanDefinitionException ex) { throw new CircularComponentScanException( "A conflicting bean definition was detected while processing @ComponentScan annotations. " + "This usually indicates a circle between scanned packages.", ex); } } } } // process any @Import annotations List<Map<String, Object>> allImportAttribs = AnnotationUtils.findAllAnnotationAttributes(Import.class, metadata.getClassName(), true); for (Map<String, Object> importAttribs : allImportAttribs) { processImport(configClass, (String[]) importAttribs.get("value"), true); } // process any @ImportResource annotations if (metadata.isAnnotated(ImportResource.class.getName())) { String[] resources = (String[]) metadata.getAnnotationAttributes(ImportResource.class.getName()).get("value"); Class<?> readerClass = (Class<?>) metadata.getAnnotationAttributes(ImportResource.class.getName()).get("reader"); if (readerClass == null) { throw new IllegalStateException( "No reader class associated with imported resources: " + StringUtils.arrayToCommaDelimitedString(resources)); } for (String resource : resources) { configClass.addImportedResource(resource, readerClass); } } // process individual @Bean methods Set<MethodMetadata> beanMethods = metadata.getAnnotatedMethods(Bean.class.getName()); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } }