Introduce ReflectionUtils#getUniqueDeclaredMethods

This change is in support of certain polymorphism cases in
@Configuration class inheritance hierarchies.  Consider the following
scenario:

@Configuration
public abstract class AbstractConfig {
    public abstract Object bean();
}

@Configuration
public class ConcreteConfig {
    @Override
    @Bean
    public BeanPostProcessor bean() { ... }
}

ConcreteConfig overrides AbstractConfig's #bean() method with a
covariant return type, in this case returning an object of type
BeanPostProcessor.  It is critically important that the container
is able to detect the return type of ConcreteConfig#bean() in order
to instantiate the BPP at the right point in the lifecycle.

Prior to this change, the container could not do this.
AbstractAutowireCapableBeanFactory#getTypeForFactoryMethod called
ReflectionUtils#getAllDeclaredMethods, which returned Method objects
for both the Object and BeanPostProcessor signatures of the #bean()
method.  This confused the implementation sufficiently as not to
choose a type for the factory method at all.  This means that the
BPP never gets detected as a BPP.

The new method being introduced here, #getUniqueDeclaredMethods, takes
covariant return types into account, and filters out duplicates,
favoring the most specific / narrow return type.

Additionally, it filters out any CGLIB 'rewritten' methods, which
is important in the case of @Configuration classes, which are
enhanced by CGLIB.  See the implementation for further details.
This commit is contained in:
Chris Beams
2011-05-06 19:07:25 +00:00
parent 2bc3527f76
commit 7b999c676f
5 changed files with 212 additions and 2 deletions

View File

@@ -631,7 +631,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// If all factory methods have the same return type, return that type.
// Can't clearly figure out exact method due to type converting / autowiring!
int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass);
Set<Class> returnTypes = new HashSet<Class>(1);
for (Method factoryMethod : candidates) {
if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic &&