Browse Source

ConfigurationClassParser enforces @Bean declaration order through ASM metadata

Issue: SPR-14505
pull/1026/merge
Juergen Hoeller 8 years ago
parent
commit
3295a4e6ef
  1. 29
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
  2. 10
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

29
spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java

@ -291,7 +291,7 @@ class ConfigurationClassParser { @@ -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 { @@ -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 { @@ -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 { @@ -588,7 +611,7 @@ class ConfigurationClassParser {
if (metadata instanceof StandardAnnotationMetadata) {
return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
}
return asSourceClass(configurationClass.getMetadata().getClassName());
return asSourceClass(metadata.getClassName());
}
/**

10
spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

@ -1281,15 +1281,15 @@ public class ConfigurationClassPostProcessorTests { @@ -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…
Cancel
Save