Skip to content

Commit 0972582

Browse files
committed
resolveFactoryMethodIfPossible considers nonPublicAccessAllowed and SecurityManager
Issue: SPR-11422 (cherry picked from commit 603cdea)
1 parent bc87910 commit 0972582

File tree

1 file changed

+45
-37
lines changed

1 file changed

+45
-37
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -54,12 +54,9 @@
5454
import org.springframework.util.StringUtils;
5555

5656
/**
57-
* Helper class for resolving constructors and factory methods.
57+
* Delegate for resolving constructors and factory methods.
5858
* Performs constructor resolution through argument matching.
5959
*
60-
* <p>Operates on an {@link AbstractBeanFactory} and an {@link InstantiationStrategy}.
61-
* Used by {@link AbstractAutowireCapableBeanFactory}.
62-
*
6360
* @author Juergen Hoeller
6461
* @author Rob Harrop
6562
* @author Mark Fisher
@@ -103,12 +100,12 @@ public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
103100
* @return a BeanWrapper for the new instance
104101
*/
105102
public BeanWrapper autowireConstructor(
106-
final String beanName, final RootBeanDefinition mbd, Constructor[] chosenCtors, final Object[] explicitArgs) {
103+
final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
107104

108105
BeanWrapperImpl bw = new BeanWrapperImpl();
109106
this.beanFactory.initBeanWrapper(bw);
110107

111-
Constructor constructorToUse = null;
108+
Constructor<?> constructorToUse = null;
112109
ArgumentsHolder argsHolderToUse = null;
113110
Object[] argsToUse = null;
114111

@@ -118,7 +115,7 @@ public BeanWrapper autowireConstructor(
118115
else {
119116
Object[] argsToResolve = null;
120117
synchronized (mbd.constructorArgumentLock) {
121-
constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
118+
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
122119
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
123120
// Found a cached constructor...
124121
argsToUse = mbd.resolvedConstructorArguments;
@@ -149,7 +146,7 @@ public BeanWrapper autowireConstructor(
149146
}
150147

151148
// Take specified constructors, if any.
152-
Constructor[] candidates = chosenCtors;
149+
Constructor<?>[] candidates = chosenCtors;
153150
if (candidates == null) {
154151
Class<?> beanClass = mbd.getBeanClass();
155152
try {
@@ -164,7 +161,7 @@ public BeanWrapper autowireConstructor(
164161
}
165162
AutowireUtils.sortConstructors(candidates);
166163
int minTypeDiffWeight = Integer.MAX_VALUE;
167-
Set<Constructor> ambiguousConstructors = null;
164+
Set<Constructor<?>> ambiguousConstructors = null;
168165
List<Exception> causes = null;
169166

170167
for (int i = 0; i < candidates.length; i++) {
@@ -185,7 +182,7 @@ public BeanWrapper autowireConstructor(
185182
try {
186183
String[] paramNames = null;
187184
if (constructorPropertiesAnnotationAvailable) {
188-
paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);
185+
paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
189186
}
190187
if (paramNames == null) {
191188
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
@@ -239,7 +236,7 @@ public BeanWrapper autowireConstructor(
239236
}
240237
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
241238
if (ambiguousConstructors == null) {
242-
ambiguousConstructors = new LinkedHashSet<Constructor>();
239+
ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
243240
ambiguousConstructors.add(constructorToUse);
244241
}
245242
ambiguousConstructors.add(candidate);
@@ -267,7 +264,7 @@ else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution())
267264
Object beanInstance;
268265

269266
if (System.getSecurityManager() != null) {
270-
final Constructor ctorToUse = constructorToUse;
267+
final Constructor<?> ctorToUse = constructorToUse;
271268
final Object[] argumentsToUse = argsToUse;
272269
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
273270
public Object run() {
@@ -295,18 +292,22 @@ public Object run() {
295292
* @param mbd the bean definition to check
296293
*/
297294
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
298-
Class factoryClass;
295+
Class<?> factoryClass;
296+
boolean isStatic;
299297
if (mbd.getFactoryBeanName() != null) {
300298
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
299+
isStatic = false;
301300
}
302301
else {
303302
factoryClass = mbd.getBeanClass();
303+
isStatic = true;
304304
}
305305
factoryClass = ClassUtils.getUserClass(factoryClass);
306-
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
306+
307+
Method[] candidates = getCandidateMethods(factoryClass, mbd);
307308
Method uniqueCandidate = null;
308309
for (Method candidate : candidates) {
309-
if (mbd.isFactoryMethod(candidate)) {
310+
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
310311
if (uniqueCandidate == null) {
311312
uniqueCandidate = candidate;
312313
}
@@ -321,6 +322,27 @@ else if (!Arrays.equals(uniqueCandidate.getParameterTypes(), candidate.getParame
321322
}
322323
}
323324

325+
/**
326+
* Retrieve all candidate methods for the given class, considering
327+
* the {@link RootBeanDefinition#isNonPublicAccessAllowed()} flag.
328+
* Called as the starting point for factory method determination.
329+
*/
330+
private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
331+
if (System.getSecurityManager() != null) {
332+
return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
333+
@Override
334+
public Method[] run() {
335+
return (mbd.isNonPublicAccessAllowed() ?
336+
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
337+
}
338+
});
339+
}
340+
else {
341+
return (mbd.isNonPublicAccessAllowed() ?
342+
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
343+
}
344+
}
345+
324346
/**
325347
* Instantiate the bean using a named factory method. The method may be static, if the
326348
* bean definition parameter specifies a class, rather than a "factory-bean", or
@@ -336,7 +358,9 @@ else if (!Arrays.equals(uniqueCandidate.getParameterTypes(), candidate.getParame
336358
* method, or {@code null} if none (-> use constructor argument values from bean definition)
337359
* @return a BeanWrapper for the new instance
338360
*/
339-
public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
361+
public BeanWrapper instantiateUsingFactoryMethod(
362+
final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
363+
340364
BeanWrapperImpl bw = new BeanWrapperImpl();
341365
this.beanFactory.initBeanWrapper(bw);
342366

@@ -397,27 +421,11 @@ public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final Ro
397421
// Need to determine the factory method...
398422
// Try all methods with this name to see if they match the given arguments.
399423
factoryClass = ClassUtils.getUserClass(factoryClass);
400-
Method[] rawCandidates;
401-
402-
final Class<?> factoryClazz = factoryClass;
403-
if (System.getSecurityManager() != null) {
404-
rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
405-
public Method[] run() {
406-
return (mbd.isNonPublicAccessAllowed() ?
407-
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
408-
}
409-
});
410-
}
411-
else {
412-
rawCandidates = (mbd.isNonPublicAccessAllowed() ?
413-
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
414-
}
415424

425+
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
416426
List<Method> candidateSet = new ArrayList<Method>();
417427
for (Method candidate : rawCandidates) {
418-
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
419-
candidate.getName().equals(mbd.getFactoryMethodName()) &&
420-
mbd.isFactoryMethod(candidate)) {
428+
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
421429
candidateSet.add(candidate);
422430
}
423431
}
@@ -759,7 +767,7 @@ private Object[] resolvePreparedArguments(
759767
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
760768

761769
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
762-
((Method) methodOrCtor).getParameterTypes() : ((Constructor) methodOrCtor).getParameterTypes());
770+
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
763771
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
764772
this.beanFactory.getCustomTypeConverter() : bw);
765773
BeanDefinitionValueResolver valueResolver =
@@ -881,7 +889,7 @@ private static class AutowiredArgumentMarker {
881889
*/
882890
private static class ConstructorPropertiesChecker {
883891

884-
public static String[] evaluateAnnotation(Constructor<?> candidate, int paramCount) {
892+
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
885893
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
886894
if (cp != null) {
887895
String[] names = cp.value();

0 commit comments

Comments
 (0)