ConstructorResolver exposes parameter signature from user-declared class (in case of a CGLIB-generated subclass)
Issue: SPR-14015
This commit is contained in:
parent
b6f69492a3
commit
b944283354
|
|
@ -182,8 +182,8 @@ class ConstructorResolver {
|
||||||
paramNames = pnd.getParameterNames(candidate);
|
paramNames = pnd.getParameterNames(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argsHolder = createArgumentArray(
|
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
|
||||||
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
|
getUserDeclaredConstructor(candidate), autowiring);
|
||||||
}
|
}
|
||||||
catch (UnsatisfiedDependencyException ex) {
|
catch (UnsatisfiedDependencyException ex) {
|
||||||
if (this.beanFactory.logger.isTraceEnabled()) {
|
if (this.beanFactory.logger.isTraceEnabled()) {
|
||||||
|
|
@ -446,8 +446,7 @@ class ConstructorResolver {
|
||||||
|
|
||||||
LinkedList<UnsatisfiedDependencyException> causes = null;
|
LinkedList<UnsatisfiedDependencyException> causes = null;
|
||||||
|
|
||||||
for (int i = 0; i < candidates.length; i++) {
|
for (Method candidate : candidates) {
|
||||||
Method candidate = candidates[i];
|
|
||||||
Class<?>[] paramTypes = candidate.getParameterTypes();
|
Class<?>[] paramTypes = candidate.getParameterTypes();
|
||||||
|
|
||||||
if (paramTypes.length >= minNrOfArgs) {
|
if (paramTypes.length >= minNrOfArgs) {
|
||||||
|
|
@ -800,6 +799,21 @@ class ConstructorResolver {
|
||||||
return resolvedArgs;
|
return resolvedArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
|
||||||
|
Class<?> declaringClass = constructor.getDeclaringClass();
|
||||||
|
Class<?> userClass = ClassUtils.getUserClass(declaringClass);
|
||||||
|
if (userClass != declaringClass) {
|
||||||
|
try {
|
||||||
|
return userClass.getDeclaredConstructor(constructor.getParameterTypes());
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException ex) {
|
||||||
|
// No equivalent constructor on user class (superclass)...
|
||||||
|
// Let's proceed with the given constructor as we usually would.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return constructor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template method for resolving the specified argument which is supposed to be autowired.
|
* Template method for resolving the specified argument which is supposed to be autowired.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2015 the original author or authors.
|
* Copyright 2002-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -26,6 +26,7 @@ import javax.inject.Provider;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
|
@ -103,6 +104,18 @@ public class AutowiredConfigurationTests {
|
||||||
assertSame(ctx.getBean(AutowiredConstructorConfig.class).colour, ctx.getBean(Colour.class));
|
assertSame(ctx.getBean(AutowiredConstructorConfig.class).colour, ctx.getBean(Colour.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testObjectFactoryConstructorWithTypeVariable() {
|
||||||
|
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||||
|
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(
|
||||||
|
new ClassPathResource("annotation-config.xml", ObjectFactoryConstructorConfig.class));
|
||||||
|
GenericApplicationContext ctx = new GenericApplicationContext(factory);
|
||||||
|
ctx.registerBeanDefinition("config1", new RootBeanDefinition(ObjectFactoryConstructorConfig.class));
|
||||||
|
ctx.registerBeanDefinition("config2", new RootBeanDefinition(ColorConfig.class));
|
||||||
|
ctx.refresh();
|
||||||
|
assertSame(ctx.getBean(ObjectFactoryConstructorConfig.class).colour, ctx.getBean(Colour.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAutowiredAnnotatedConstructorSupported() {
|
public void testAutowiredAnnotatedConstructorSupported() {
|
||||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||||
|
|
@ -257,6 +270,18 @@ public class AutowiredConfigurationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class ObjectFactoryConstructorConfig {
|
||||||
|
|
||||||
|
Colour colour;
|
||||||
|
|
||||||
|
// @Autowired
|
||||||
|
ObjectFactoryConstructorConfig(ObjectFactory<Colour> colourFactory) {
|
||||||
|
this.colour = colourFactory.getObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class MultipleConstructorConfig {
|
static class MultipleConstructorConfig {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue