ConfigurationClassParser enforces @Bean declaration order through ASM metadata
Issue: SPR-14505
(cherry picked from commit 3295a4e)
			
			
This commit is contained in:
		
							parent
							
								
									505480cf63
								
							
						
					
					
						commit
						4a84ee07be
					
				| 
						 | 
				
			
			@ -291,7 +291,7 @@ class ConfigurationClassParser {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		// Process individual @Bean methods
 | 
			
		||||
		Set<MethodMetadata> beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());
 | 
			
		||||
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
 | 
			
		||||
		for (MethodMetadata methodMetadata : beanMethods) {
 | 
			
		||||
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -341,7 +341,7 @@ class ConfigurationClassParser {
 | 
			
		|||
	 */
 | 
			
		||||
	private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
 | 
			
		||||
		for (SourceClass ifc : sourceClass.getInterfaces()) {
 | 
			
		||||
			Set<MethodMetadata> beanMethods = ifc.getMetadata().getAnnotatedMethods(Bean.class.getName());
 | 
			
		||||
			Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
 | 
			
		||||
			for (MethodMetadata methodMetadata : beanMethods) {
 | 
			
		||||
				if (!methodMetadata.isAbstract()) {
 | 
			
		||||
					// A default method or other concrete method on a Java 8+ interface...
 | 
			
		||||
| 
						 | 
				
			
			@ -352,6 +352,29 @@ class ConfigurationClassParser {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Retrieve the metadata for all <code>@Bean</code> methods.
 | 
			
		||||
	 */
 | 
			
		||||
	private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
 | 
			
		||||
		AnnotationMetadata original = sourceClass.getMetadata();
 | 
			
		||||
		Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
 | 
			
		||||
		if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
 | 
			
		||||
			// Try reading the class file via ASM for deterministic declaration order...
 | 
			
		||||
			// Unfortunately, the JVM's standard reflection returns methods in arbitrary
 | 
			
		||||
			// order, even between different runs of the same application on the same JVM.
 | 
			
		||||
			try {
 | 
			
		||||
				AnnotationMetadata asm =
 | 
			
		||||
						this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
 | 
			
		||||
				beanMethods = asm.getAnnotatedMethods(Bean.class.getName());
 | 
			
		||||
			}
 | 
			
		||||
			catch (IOException ex) {
 | 
			
		||||
				logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
 | 
			
		||||
				// No worries, let's continue with the reflection metadata we started with...
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return beanMethods;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Process the given <code>@PropertySource</code> annotation metadata.
 | 
			
		||||
	 * @param propertySource metadata for the <code>@PropertySource</code> annotation found
 | 
			
		||||
| 
						 | 
				
			
			@ -588,7 +611,7 @@ class ConfigurationClassParser {
 | 
			
		|||
		if (metadata instanceof StandardAnnotationMetadata) {
 | 
			
		||||
			return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
 | 
			
		||||
		}
 | 
			
		||||
		return asSourceClass(configurationClass.getMetadata().getClassName());
 | 
			
		||||
		return asSourceClass(metadata.getClassName());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1281,15 +1281,15 @@ public class ConfigurationClassPostProcessorTests {
 | 
			
		|||
	@Configuration
 | 
			
		||||
	static class FooBarConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean @DependsOn("bar")
 | 
			
		||||
		public FooImpl foo() {
 | 
			
		||||
			return new FooImpl();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public BarInterface bar() {
 | 
			
		||||
			return new BarImpl();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public FooImpl foo() {
 | 
			
		||||
			return new FooImpl();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue