ConstructorResolver exposes parameter signature from user-declared class (in case of a CGLIB-generated subclass)

Issue: SPR-14015
master
Juergen Hoeller 9 years ago
parent b6f69492a3
commit b944283354
  1. 22
      spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
  2. 27
      spring-context/src/test/java/org/springframework/context/annotation/configuration/AutowiredConfigurationTests.java

@ -182,8 +182,8 @@ class ConstructorResolver {
paramNames = pnd.getParameterNames(candidate);
}
}
argsHolder = createArgumentArray(
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring);
}
catch (UnsatisfiedDependencyException ex) {
if (this.beanFactory.logger.isTraceEnabled()) {
@ -446,8 +446,7 @@ class ConstructorResolver {
LinkedList<UnsatisfiedDependencyException> causes = null;
for (int i = 0; i < candidates.length; i++) {
Method candidate = candidates[i];
for (Method candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
@ -800,6 +799,21 @@ class ConstructorResolver {
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.
*/

@ -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");
* 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.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@ -103,6 +104,18 @@ public class AutowiredConfigurationTests {
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
public void testAutowiredAnnotatedConstructorSupported() {
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
static class MultipleConstructorConfig {

Loading…
Cancel
Save