Support by-type constructor references via RuntimeBeanReference

Closes gh-28728
This commit is contained in:
Juergen Hoeller 2022-06-29 17:02:33 +02:00
parent a21b27e6d9
commit d2e27ad754
2 changed files with 79 additions and 135 deletions

View File

@ -30,9 +30,7 @@ import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.commons.logging.Log; import org.springframework.beans.BeanUtils;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
@ -40,6 +38,7 @@ import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
@ -62,57 +61,52 @@ import org.springframework.util.ReflectionUtils;
*/ */
class ConstructorOrFactoryMethodResolver { class ConstructorOrFactoryMethodResolver {
private static final Log logger = LogFactory
.getLog(ConstructorOrFactoryMethodResolver.class);
private final ConfigurableBeanFactory beanFactory; private final ConfigurableBeanFactory beanFactory;
@Nullable
private final ClassLoader classLoader; private final ClassLoader classLoader;
ConstructorOrFactoryMethodResolver(ConfigurableBeanFactory beanFactory) { ConstructorOrFactoryMethodResolver(ConfigurableBeanFactory beanFactory) {
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
this.classLoader = (beanFactory.getBeanClassLoader() != null) this.classLoader = (beanFactory.getBeanClassLoader() != null ?
? beanFactory.getBeanClassLoader() : ClassUtils.getDefaultClassLoader(); beanFactory.getBeanClassLoader() : ClassUtils.getDefaultClassLoader());
} }
@Nullable
Executable resolve(BeanDefinition beanDefinition) { Executable resolve(BeanDefinition beanDefinition) {
Supplier<ResolvableType> beanType = () -> getBeanType(beanDefinition); Supplier<ResolvableType> beanType = () -> getBeanType(beanDefinition);
List<ResolvableType> valueTypes = beanDefinition.hasConstructorArgumentValues() List<ResolvableType> valueTypes = (beanDefinition.hasConstructorArgumentValues() ?
? determineParameterValueTypes( determineParameterValueTypes(beanDefinition.getConstructorArgumentValues()) :
beanDefinition.getConstructorArgumentValues()) Collections.emptyList());
: Collections.emptyList();
Method resolvedFactoryMethod = resolveFactoryMethod(beanDefinition, valueTypes); Method resolvedFactoryMethod = resolveFactoryMethod(beanDefinition, valueTypes);
if (resolvedFactoryMethod != null) { if (resolvedFactoryMethod != null) {
return resolvedFactoryMethod; return resolvedFactoryMethod;
} }
Class<?> factoryBeanClass = getFactoryBeanClass(beanDefinition); Class<?> factoryBeanClass = getFactoryBeanClass(beanDefinition);
if (factoryBeanClass != null && !factoryBeanClass if (factoryBeanClass != null && !factoryBeanClass.equals(beanDefinition.getResolvableType().toClass())) {
.equals(beanDefinition.getResolvableType().toClass())) {
ResolvableType resolvableType = beanDefinition.getResolvableType(); ResolvableType resolvableType = beanDefinition.getResolvableType();
boolean isCompatible = ResolvableType.forClass(factoryBeanClass) boolean isCompatible = ResolvableType.forClass(factoryBeanClass)
.as(FactoryBean.class).getGeneric(0).isAssignableFrom(resolvableType); .as(FactoryBean.class).getGeneric(0).isAssignableFrom(resolvableType);
Assert.state(isCompatible, Assert.state(isCompatible, () -> String.format(
() -> String.format(
"Incompatible target type '%s' for factory bean '%s'", "Incompatible target type '%s' for factory bean '%s'",
resolvableType.toClass().getName(), resolvableType.toClass().getName(), factoryBeanClass.getName()));
factoryBeanClass.getName())); return resolveConstructor(() -> ResolvableType.forClass(factoryBeanClass), valueTypes);
return resolveConstructor(() -> ResolvableType.forClass(factoryBeanClass),
valueTypes);
} }
Executable resolvedConstructor = resolveConstructor(beanType, valueTypes); Executable resolvedConstructor = resolveConstructor(beanType, valueTypes);
if (resolvedConstructor != null) { if (resolvedConstructor != null) {
return resolvedConstructor; return resolvedConstructor;
} }
Executable resolvedConstructorOrFactoryMethod = getField(beanDefinition,
"resolvedConstructorOrFactoryMethod", Executable.class); Field field = ReflectionUtils.findField(RootBeanDefinition.class, "resolvedConstructorOrFactoryMethod");
if (resolvedConstructorOrFactoryMethod != null) { if (field != null) {
logger.error( ReflectionUtils.makeAccessible(field);
"resolvedConstructorOrFactoryMethod required for " + beanDefinition); return (Executable) ReflectionUtils.getField(field, beanDefinition);
return resolvedConstructorOrFactoryMethod;
} }
return null; return null;
} }
@ -132,15 +126,19 @@ class ConstructorOrFactoryMethodResolver {
return ResolvableType.forClass(loadClass(valueHolder.getType())); return ResolvableType.forClass(loadClass(valueHolder.getType()));
} }
Object value = valueHolder.getValue(); Object value = valueHolder.getValue();
if (value instanceof BeanReference) { if (value instanceof BeanReference br) {
return ResolvableType.forClass(this.beanFactory if (value instanceof RuntimeBeanReference rbr) {
.getType(((BeanReference) value).getBeanName(), false)); if (rbr.getBeanType() != null) {
return ResolvableType.forClass(rbr.getBeanType());
} }
if (value instanceof BeanDefinition) {
return extractTypeFromBeanDefinition(getBeanType((BeanDefinition) value));
} }
if (value instanceof Class<?>) { return ResolvableType.forClass(this.beanFactory.getType(br.getBeanName(), false));
return ResolvableType.forClassWithGenerics(Class.class, (Class<?>) value); }
if (value instanceof BeanDefinition bd) {
return extractTypeFromBeanDefinition(getBeanType(bd));
}
if (value instanceof Class<?> clazz) {
return ResolvableType.forClassWithGenerics(Class.class, clazz);
} }
return ResolvableType.forInstance(value); return ResolvableType.forInstance(value);
} }
@ -153,9 +151,7 @@ class ConstructorOrFactoryMethodResolver {
} }
@Nullable @Nullable
private Method resolveFactoryMethod(BeanDefinition beanDefinition, private Method resolveFactoryMethod(BeanDefinition beanDefinition, List<ResolvableType> valueTypes) {
List<ResolvableType> valueTypes) {
if (beanDefinition instanceof RootBeanDefinition rbd) { if (beanDefinition instanceof RootBeanDefinition rbd) {
Method resolvedFactoryMethod = rbd.getResolvedFactoryMethod(); Method resolvedFactoryMethod = rbd.getResolvedFactoryMethod();
if (resolvedFactoryMethod != null) { if (resolvedFactoryMethod != null) {
@ -165,15 +161,13 @@ class ConstructorOrFactoryMethodResolver {
String factoryMethodName = beanDefinition.getFactoryMethodName(); String factoryMethodName = beanDefinition.getFactoryMethodName();
if (factoryMethodName != null) { if (factoryMethodName != null) {
String factoryBeanName = beanDefinition.getFactoryBeanName(); String factoryBeanName = beanDefinition.getFactoryBeanName();
Class<?> beanClass = getBeanClass((factoryBeanName != null) Class<?> beanClass = getBeanClass(factoryBeanName != null ?
? this.beanFactory.getMergedBeanDefinition(factoryBeanName) this.beanFactory.getMergedBeanDefinition(factoryBeanName) : beanDefinition);
: beanDefinition);
List<Method> methods = new ArrayList<>(); List<Method> methods = new ArrayList<>();
Assert.state(beanClass != null, Assert.state(beanClass != null,
() -> "Failed to determine bean class of " + beanDefinition); () -> "Failed to determine bean class of " + beanDefinition);
ReflectionUtils.doWithMethods(beanClass, methods::add, ReflectionUtils.doWithMethods(beanClass, methods::add,
method -> isFactoryMethodCandidate(beanClass, method, method -> isFactoryMethodCandidate(beanClass, method, factoryMethodName));
factoryMethodName));
if (methods.size() >= 1) { if (methods.size() >= 1) {
Function<Method, List<ResolvableType>> parameterTypesFactory = method -> { Function<Method, List<ResolvableType>> parameterTypesFactory = method -> {
List<ResolvableType> types = new ArrayList<>(); List<ResolvableType> types = new ArrayList<>();
@ -182,16 +176,13 @@ class ConstructorOrFactoryMethodResolver {
} }
return types; return types;
}; };
return (Method) resolveFactoryMethod(methods, parameterTypesFactory, return (Method) resolveFactoryMethod(methods, parameterTypesFactory, valueTypes);
valueTypes);
} }
} }
return null; return null;
} }
private boolean isFactoryMethodCandidate(Class<?> beanClass, Method method, private boolean isFactoryMethodCandidate(Class<?> beanClass, Method method, String factoryMethodName) {
String factoryMethodName) {
if (method.getName().equals(factoryMethodName)) { if (method.getName().equals(factoryMethodName)) {
if (Modifier.isStatic(method.getModifiers())) { if (Modifier.isStatic(method.getModifiers())) {
return method.getDeclaringClass().equals(beanClass); return method.getDeclaringClass().equals(beanClass);
@ -202,9 +193,7 @@ class ConstructorOrFactoryMethodResolver {
} }
@Nullable @Nullable
private Executable resolveConstructor(Supplier<ResolvableType> beanType, private Executable resolveConstructor(Supplier<ResolvableType> beanType, List<ResolvableType> valueTypes) {
List<ResolvableType> valueTypes) {
Class<?> type = ClassUtils.getUserClass(beanType.get().toClass()); Class<?> type = ClassUtils.getUserClass(beanType.get().toClass());
Constructor<?>[] constructors = type.getDeclaredConstructors(); Constructor<?>[] constructors = type.getDeclaredConstructors();
if (constructors.length == 1) { if (constructors.length == 1) {
@ -240,47 +229,41 @@ class ConstructorOrFactoryMethodResolver {
List<? extends Executable> typeConversionFallbackMatches = Arrays List<? extends Executable> typeConversionFallbackMatches = Arrays
.stream(constructors) .stream(constructors)
.filter(executable -> match(parameterTypesFactory.apply(executable), .filter(executable -> match(parameterTypesFactory.apply(executable),
valueTypes, valueTypes, FallbackMode.TYPE_CONVERSION))
ConstructorOrFactoryMethodResolver.FallbackMode.TYPE_CONVERSION))
.toList(); .toList();
return (typeConversionFallbackMatches.size() == 1) return (typeConversionFallbackMatches.size() == 1)
? typeConversionFallbackMatches.get(0) : null; ? typeConversionFallbackMatches.get(0) : null;
} }
@Nullable
private Executable resolveFactoryMethod(List<Method> executables, private Executable resolveFactoryMethod(List<Method> executables,
Function<Method, List<ResolvableType>> parameterTypesFactory, Function<Method, List<ResolvableType>> parameterTypesFactory,
List<ResolvableType> valueTypes) { List<ResolvableType> valueTypes) {
List<? extends Executable> matches = executables.stream() List<? extends Executable> matches = executables.stream()
.filter(executable -> match(parameterTypesFactory.apply(executable), .filter(executable -> match(parameterTypesFactory.apply(executable), valueTypes, FallbackMode.NONE))
valueTypes, ConstructorOrFactoryMethodResolver.FallbackMode.NONE))
.toList(); .toList();
if (matches.size() == 1) { if (matches.size() == 1) {
return matches.get(0); return matches.get(0);
} }
List<? extends Executable> assignableElementFallbackMatches = executables.stream() List<? extends Executable> assignableElementFallbackMatches = executables.stream()
.filter(executable -> match(parameterTypesFactory.apply(executable), .filter(executable -> match(parameterTypesFactory.apply(executable),
valueTypes, valueTypes, FallbackMode.ASSIGNABLE_ELEMENT))
ConstructorOrFactoryMethodResolver.FallbackMode.ASSIGNABLE_ELEMENT))
.toList(); .toList();
if (assignableElementFallbackMatches.size() == 1) { if (assignableElementFallbackMatches.size() == 1) {
return assignableElementFallbackMatches.get(0); return assignableElementFallbackMatches.get(0);
} }
List<? extends Executable> typeConversionFallbackMatches = executables.stream() List<? extends Executable> typeConversionFallbackMatches = executables.stream()
.filter(executable -> match(parameterTypesFactory.apply(executable), .filter(executable -> match(parameterTypesFactory.apply(executable),
valueTypes, valueTypes, FallbackMode.TYPE_CONVERSION))
ConstructorOrFactoryMethodResolver.FallbackMode.TYPE_CONVERSION))
.toList(); .toList();
Assert.state(typeConversionFallbackMatches.size() <= 1, Assert.state(typeConversionFallbackMatches.size() <= 1,
() -> "Multiple matches with parameters '" + valueTypes + "': " () -> "Multiple matches with parameters '" + valueTypes + "': " + typeConversionFallbackMatches);
+ typeConversionFallbackMatches); return (typeConversionFallbackMatches.size() == 1 ? typeConversionFallbackMatches.get(0) : null);
return (typeConversionFallbackMatches.size() == 1)
? typeConversionFallbackMatches.get(0) : null;
} }
private boolean match(List<ResolvableType> parameterTypes, private boolean match(
List<ResolvableType> valueTypes, List<ResolvableType> parameterTypes, List<ResolvableType> valueTypes, FallbackMode fallbackMode) {
ConstructorOrFactoryMethodResolver.FallbackMode fallbackMode) {
if (parameterTypes.size() != valueTypes.size()) { if (parameterTypes.size() != valueTypes.size()) {
return false; return false;
@ -293,15 +276,12 @@ class ConstructorOrFactoryMethodResolver {
return true; return true;
} }
private boolean isMatch(ResolvableType parameterType, ResolvableType valueType, private boolean isMatch(ResolvableType parameterType, ResolvableType valueType, FallbackMode fallbackMode) {
ConstructorOrFactoryMethodResolver.FallbackMode fallbackMode) {
if (isAssignable(valueType).test(parameterType)) { if (isAssignable(valueType).test(parameterType)) {
return true; return true;
} }
return switch (fallbackMode) { return switch (fallbackMode) {
case ASSIGNABLE_ELEMENT -> isAssignable(valueType) case ASSIGNABLE_ELEMENT -> isAssignable(valueType).test(extractElementType(parameterType));
.test(extractElementType(parameterType));
case TYPE_CONVERSION -> typeConversionFallback(valueType).test(parameterType); case TYPE_CONVERSION -> typeConversionFallback(valueType).test(parameterType);
default -> false; default -> false;
}; };
@ -323,12 +303,10 @@ class ConstructorOrFactoryMethodResolver {
private Predicate<ResolvableType> typeConversionFallback(ResolvableType valueType) { private Predicate<ResolvableType> typeConversionFallback(ResolvableType valueType) {
return parameterType -> { return parameterType -> {
if (valueOrCollection(valueType, this::isStringForClassFallback) if (valueOrCollection(valueType, this::isStringForClassFallback).test(parameterType)) {
.test(parameterType)) {
return true; return true;
} }
return valueOrCollection(valueType, this::isSimpleConvertibleType) return valueOrCollection(valueType, this::isSimpleValueType).test(parameterType);
.test(parameterType);
}; };
} }
@ -339,12 +317,10 @@ class ConstructorOrFactoryMethodResolver {
if (predicateProvider.apply(valueType).test(parameterType)) { if (predicateProvider.apply(valueType).test(parameterType)) {
return true; return true;
} }
if (predicateProvider.apply(extractElementType(valueType)) if (predicateProvider.apply(extractElementType(valueType)).test(extractElementType(parameterType))) {
.test(extractElementType(parameterType))) {
return true; return true;
} }
return (predicateProvider.apply(valueType) return (predicateProvider.apply(valueType).test(extractElementType(parameterType)));
.test(extractElementType(parameterType)));
}; };
} }
@ -358,13 +334,13 @@ class ConstructorOrFactoryMethodResolver {
* parameter * parameter
*/ */
private Predicate<ResolvableType> isStringForClassFallback(ResolvableType valueType) { private Predicate<ResolvableType> isStringForClassFallback(ResolvableType valueType) {
return parameterType -> (valueType.isAssignableFrom(String.class) return parameterType -> (valueType.isAssignableFrom(String.class) &&
&& parameterType.isAssignableFrom(Class.class)); parameterType.isAssignableFrom(Class.class));
} }
private Predicate<ResolvableType> isSimpleConvertibleType(ResolvableType valueType) { private Predicate<ResolvableType> isSimpleValueType(ResolvableType valueType) {
return parameterType -> isSimpleConvertibleType(parameterType.toClass()) return parameterType -> (BeanUtils.isSimpleValueType(parameterType.toClass()) &&
&& isSimpleConvertibleType(valueType.toClass()); BeanUtils.isSimpleValueType(valueType.toClass()));
} }
@Nullable @Nullable
@ -372,7 +348,7 @@ class ConstructorOrFactoryMethodResolver {
if (beanDefinition instanceof RootBeanDefinition rbd) { if (beanDefinition instanceof RootBeanDefinition rbd) {
if (rbd.hasBeanClass()) { if (rbd.hasBeanClass()) {
Class<?> beanClass = rbd.getBeanClass(); Class<?> beanClass = rbd.getBeanClass();
return FactoryBean.class.isAssignableFrom(beanClass) ? beanClass : null; return (FactoryBean.class.isAssignableFrom(beanClass) ? beanClass : null);
} }
} }
return null; return null;
@ -380,12 +356,10 @@ class ConstructorOrFactoryMethodResolver {
@Nullable @Nullable
private Class<?> getBeanClass(BeanDefinition beanDefinition) { private Class<?> getBeanClass(BeanDefinition beanDefinition) {
if (beanDefinition instanceof AbstractBeanDefinition abd) { if (beanDefinition instanceof AbstractBeanDefinition abd && abd.hasBeanClass()) {
return abd.hasBeanClass() ? abd.getBeanClass() return abd.getBeanClass();
: loadClass(abd.getBeanClassName());
} }
return (beanDefinition.getBeanClassName() != null) return (beanDefinition.getBeanClassName() != null ? loadClass(beanDefinition.getBeanClassName()) : null);
? loadClass(beanDefinition.getBeanClassName()) : null;
} }
private ResolvableType getBeanType(BeanDefinition beanDefinition) { private ResolvableType getBeanType(BeanDefinition beanDefinition) {
@ -416,21 +390,6 @@ class ConstructorOrFactoryMethodResolver {
} }
@Nullable @Nullable
private <T> T getField(BeanDefinition beanDefinition, String fieldName,
Class<T> targetType) {
Field field = ReflectionUtils.findField(RootBeanDefinition.class, fieldName);
ReflectionUtils.makeAccessible(field);
return targetType.cast(ReflectionUtils.getField(field, beanDefinition));
}
private static boolean isSimpleConvertibleType(Class<?> type) {
return (type.isPrimitive() && type != void.class) || type == Double.class
|| type == Float.class || type == Long.class || type == Integer.class
|| type == Short.class || type == Character.class || type == Byte.class
|| type == Boolean.class || type == String.class;
}
static Executable resolve(RegisteredBean registeredBean) { static Executable resolve(RegisteredBean registeredBean) {
return new ConstructorOrFactoryMethodResolver(registeredBean.getBeanFactory()) return new ConstructorOrFactoryMethodResolver(registeredBean.getBeanFactory())
.resolve(registeredBean.getMergedBeanDefinition()); .resolve(registeredBean.getMergedBeanDefinition());
@ -444,7 +403,6 @@ class ConstructorOrFactoryMethodResolver {
ASSIGNABLE_ELEMENT, ASSIGNABLE_ELEMENT,
TYPE_CONVERSION TYPE_CONVERSION
} }
} }

View File

@ -141,8 +141,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithMultiArgConstructorAndMatchingValue() void beanDefinitionWithMultiArgConstructorAndMatchingValue() throws NoSuchMethodException {
throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSample.class) .rootBeanDefinition(MultiConstructorSample.class)
.addConstructorArgValue(42).getBeanDefinition(); .addConstructorArgValue(42).getBeanDefinition();
@ -152,8 +151,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithMultiArgConstructorAndMatchingArrayValue() void beanDefinitionWithMultiArgConstructorAndMatchingArrayValue() throws NoSuchMethodException {
throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorArraySample.class) .rootBeanDefinition(MultiConstructorArraySample.class)
.addConstructorArgValue(42).getBeanDefinition(); .addConstructorArgValue(42).getBeanDefinition();
@ -163,8 +161,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithMultiArgConstructorAndMatchingListValue() void beanDefinitionWithMultiArgConstructorAndMatchingListValue() throws NoSuchMethodException {
throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorListSample.class) .rootBeanDefinition(MultiConstructorListSample.class)
.addConstructorArgValue(42).getBeanDefinition(); .addConstructorArgValue(42).getBeanDefinition();
@ -174,8 +171,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithMultiArgConstructorAndMatchingValueAsInnerBean() void beanDefinitionWithMultiArgConstructorAndMatchingValueAsInnerBean() throws NoSuchMethodException {
throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSample.class) .rootBeanDefinition(MultiConstructorSample.class)
.addConstructorArgValue( .addConstructorArgValue(
@ -188,8 +184,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithMultiArgConstructorAndMatchingValueAsInnerBeanFactory() void beanDefinitionWithMultiArgConstructorAndMatchingValueAsInnerBeanFactory() throws NoSuchMethodException {
throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSample.class) .rootBeanDefinition(MultiConstructorSample.class)
.addConstructorArgValue(BeanDefinitionBuilder .addConstructorArgValue(BeanDefinitionBuilder
@ -258,8 +253,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithClassArrayConstructorArgAndStringArrayValueType() void beanDefinitionWithClassArrayConstructorArgAndStringArrayValueType() throws NoSuchMethodException {
throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(ConstructorClassArraySample.class.getName()) .rootBeanDefinition(ConstructorClassArraySample.class.getName())
@ -282,8 +276,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithClassArrayConstructorArgAndAnotherMatchingConstructor() void beanDefinitionWithClassArrayConstructorArgAndAnotherMatchingConstructor() throws NoSuchMethodException {
throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorClassArraySample.class.getName()) .rootBeanDefinition(MultiConstructorClassArraySample.class.getName())
@ -323,8 +316,7 @@ class ConstructorOrFactoryMethodResolverTests {
} }
@Test @Test
void beanDefinitionWithMultiArgConstructorAndPrimitiveConversion() void beanDefinitionWithMultiArgConstructorAndPrimitiveConversion() throws NoSuchMethodException {
throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(ConstructorPrimitiveFallback.class) .rootBeanDefinition(ConstructorPrimitiveFallback.class)
.addConstructorArgValue("true").getBeanDefinition(); .addConstructorArgValue("true").getBeanDefinition();
@ -345,12 +337,13 @@ class ConstructorOrFactoryMethodResolverTests {
Class.class)); Class.class));
} }
private Executable resolve(DefaultListableBeanFactory beanFactory,
BeanDefinition beanDefinition) { @Nullable
return new ConstructorOrFactoryMethodResolver(beanFactory) private Executable resolve(DefaultListableBeanFactory beanFactory, BeanDefinition beanDefinition) {
.resolve(beanDefinition); return new ConstructorOrFactoryMethodResolver(beanFactory).resolve(beanDefinition);
} }
static class IntegerFactoryBean implements FactoryBean<Integer> { static class IntegerFactoryBean implements FactoryBean<Integer> {
@Override @Override
@ -372,7 +365,6 @@ class ConstructorOrFactoryMethodResolverTests {
MultiConstructorSample(Integer value) { MultiConstructorSample(Integer value) {
} }
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -393,7 +385,6 @@ class ConstructorOrFactoryMethodResolverTests {
public MultiConstructorListSample(List<Integer> values) { public MultiConstructorListSample(List<Integer> values) {
} }
} }
interface DummyInterface { interface DummyInterface {
@ -441,7 +432,6 @@ class ConstructorOrFactoryMethodResolverTests {
static String of(Class<?>[] classArrayArg) { static String of(Class<?>[] classArrayArg) {
return "test"; return "test";
} }
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -454,7 +444,6 @@ class ConstructorOrFactoryMethodResolverTests {
static String of(String[] classArrayArg) { static String of(String[] classArrayArg) {
return "test"; return "test";
} }
} }
@SuppressWarnings("unnused") @SuppressWarnings("unnused")
@ -465,7 +454,6 @@ class ConstructorOrFactoryMethodResolverTests {
public ConstructorPrimitiveFallback(Executor executor) { public ConstructorPrimitiveFallback(Executor executor) {
} }
} }
static class SampleBeanWithConstructors { static class SampleBeanWithConstructors {
@ -478,7 +466,6 @@ class ConstructorOrFactoryMethodResolverTests {
public SampleBeanWithConstructors(Number number, String name) { public SampleBeanWithConstructors(Number number, String name) {
} }
} }
interface FactoryWithOverloadedClassMethodsOnInterface { interface FactoryWithOverloadedClassMethodsOnInterface {
@ -493,7 +480,6 @@ class ConstructorOrFactoryMethodResolverTests {
SearchStrategy searchStrategy) { SearchStrategy searchStrategy) {
return null; return null;
} }
} }
} }