|  | 
| 17 | 17 | package org.springframework.context.annotation; | 
| 18 | 18 | 
 | 
| 19 | 19 | import java.beans.PropertyDescriptor; | 
|  | 20 | +import java.util.Arrays; | 
| 20 | 21 | import java.util.HashSet; | 
| 21 | 22 | import java.util.LinkedHashMap; | 
| 22 | 23 | import java.util.LinkedHashSet; | 
| @@ -269,7 +270,9 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) | 
| 269 | 270 | 	 */ | 
| 270 | 271 | 	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { | 
| 271 | 272 | 		Set<BeanDefinitionHolder> configCandidates = new LinkedHashSet<BeanDefinitionHolder>(); | 
| 272 |  | -		for (String beanName : registry.getBeanDefinitionNames()) { | 
|  | 273 | +		String[] candidateNames = registry.getBeanDefinitionNames(); | 
|  | 274 | + | 
|  | 275 | +		for (String beanName : candidateNames) { | 
| 273 | 276 | 			BeanDefinition beanDef = registry.getBeanDefinition(beanName); | 
| 274 | 277 | 			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || | 
| 275 | 278 | 					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { | 
| @@ -302,32 +305,59 @@ else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this. | 
| 302 | 305 | 		ConfigurationClassParser parser = new ConfigurationClassParser( | 
| 303 | 306 | 				this.metadataReaderFactory, this.problemReporter, this.environment, | 
| 304 | 307 | 				this.resourceLoader, this.componentScanBeanNameGenerator, registry); | 
| 305 |  | -		parser.parse(configCandidates); | 
| 306 |  | -		parser.validate(); | 
| 307 |  | - | 
| 308 |  | -		// Handle any @PropertySource annotations | 
| 309 |  | -		List<PropertySource<?>> parsedPropertySources = parser.getPropertySources(); | 
| 310 |  | -		if (!parsedPropertySources.isEmpty()) { | 
| 311 |  | -			if (!(this.environment instanceof ConfigurableEnvironment)) { | 
| 312 |  | -				logger.warn("Ignoring @PropertySource annotations. " + | 
| 313 |  | -						"Reason: Environment must implement ConfigurableEnvironment"); | 
| 314 |  | -			} | 
| 315 |  | -			else { | 
| 316 |  | -				MutablePropertySources envPropertySources = ((ConfigurableEnvironment) this.environment).getPropertySources(); | 
| 317 |  | -				for (PropertySource<?> propertySource : parsedPropertySources) { | 
| 318 |  | -					envPropertySources.addLast(propertySource); | 
|  | 308 | + | 
|  | 309 | +		Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size()); | 
|  | 310 | +		int propertySourceCount = 0; | 
|  | 311 | +		do { | 
|  | 312 | +			parser.parse(configCandidates); | 
|  | 313 | +			parser.validate(); | 
|  | 314 | + | 
|  | 315 | +			// Handle any @PropertySource annotations | 
|  | 316 | +			if (parser.getPropertySourceCount() > propertySourceCount) { | 
|  | 317 | +				List<PropertySource<?>> parsedPropertySources = parser.getPropertySources(); | 
|  | 318 | +				if (!parsedPropertySources.isEmpty()) { | 
|  | 319 | +					if (!(this.environment instanceof ConfigurableEnvironment)) { | 
|  | 320 | +						logger.warn("Ignoring @PropertySource annotations. " + | 
|  | 321 | +								"Reason: Environment must implement ConfigurableEnvironment"); | 
|  | 322 | +					} | 
|  | 323 | +					else { | 
|  | 324 | +						MutablePropertySources envPropertySources = ((ConfigurableEnvironment) this.environment).getPropertySources(); | 
|  | 325 | +						for (PropertySource<?> propertySource : parsedPropertySources) { | 
|  | 326 | +							envPropertySources.addLast(propertySource); | 
|  | 327 | +						} | 
|  | 328 | +					} | 
| 319 | 329 | 				} | 
|  | 330 | +				propertySourceCount = parser.getPropertySourceCount(); | 
| 320 | 331 | 			} | 
| 321 |  | -		} | 
| 322 | 332 | 
 | 
| 323 |  | -		// Read the model and create bean definitions based on its content | 
| 324 |  | -		if (this.reader == null) { | 
| 325 |  | -			this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, | 
| 326 |  | -					this.problemReporter, this.metadataReaderFactory, this.resourceLoader, this.environment, | 
| 327 |  | -					this.importBeanNameGenerator); | 
| 328 |  | -		} | 
|  | 333 | +			Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses()); | 
|  | 334 | +			configClasses.removeAll(alreadyParsed); | 
| 329 | 335 | 
 | 
| 330 |  | -		this.reader.loadBeanDefinitions(parser.getConfigurationClasses()); | 
|  | 336 | +			// Read the model and create bean definitions based on its content | 
|  | 337 | +			if (this.reader == null) { | 
|  | 338 | +				this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, | 
|  | 339 | +						this.problemReporter, this.metadataReaderFactory, this.resourceLoader, this.environment, | 
|  | 340 | +						this.importBeanNameGenerator); | 
|  | 341 | +			} | 
|  | 342 | +			this.reader.loadBeanDefinitions(configClasses); | 
|  | 343 | +			alreadyParsed.addAll(configClasses); | 
|  | 344 | + | 
|  | 345 | +			configCandidates.clear(); | 
|  | 346 | +			if (registry.getBeanDefinitionCount() > candidateNames.length) { | 
|  | 347 | +				String[] newCandidateNames = registry.getBeanDefinitionNames(); | 
|  | 348 | +				Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames)); | 
|  | 349 | +				for (String candidateName : newCandidateNames) { | 
|  | 350 | +					if (!oldCandidateNames.contains(candidateName)) { | 
|  | 351 | +						BeanDefinition beanDef = registry.getBeanDefinition(candidateName); | 
|  | 352 | +						if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { | 
|  | 353 | +							configCandidates.add(new BeanDefinitionHolder(beanDef, candidateName)); | 
|  | 354 | +						} | 
|  | 355 | +					} | 
|  | 356 | +				} | 
|  | 357 | +				candidateNames = newCandidateNames; | 
|  | 358 | +			} | 
|  | 359 | +		} | 
|  | 360 | +		while (!configCandidates.isEmpty()); | 
| 331 | 361 | 
 | 
| 332 | 362 | 		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes | 
| 333 | 363 | 		if (singletonRegistry != null) { | 
|  | 
0 commit comments