resolveFactoryMethodIfPossible considers nonPublicAccessAllowed and SecurityManager
Issue: SPR-11422
This commit is contained in:
@@ -71,11 +71,6 @@ import org.springframework.util.StringUtils;
|
|||||||
*/
|
*/
|
||||||
class ConstructorResolver {
|
class ConstructorResolver {
|
||||||
|
|
||||||
private static final String CONSTRUCTOR_PROPERTIES_CLASS_NAME = "java.beans.ConstructorProperties";
|
|
||||||
|
|
||||||
private static final boolean constructorPropertiesAnnotationAvailable =
|
|
||||||
ClassUtils.isPresent(CONSTRUCTOR_PROPERTIES_CLASS_NAME, ConstructorResolver.class.getClassLoader());
|
|
||||||
|
|
||||||
private final AbstractAutowireCapableBeanFactory beanFactory;
|
private final AbstractAutowireCapableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
|
||||||
@@ -183,10 +178,7 @@ class ConstructorResolver {
|
|||||||
ArgumentsHolder argsHolder;
|
ArgumentsHolder argsHolder;
|
||||||
if (resolvedValues != null) {
|
if (resolvedValues != null) {
|
||||||
try {
|
try {
|
||||||
String[] paramNames = null;
|
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
|
||||||
if (constructorPropertiesAnnotationAvailable) {
|
|
||||||
paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);
|
|
||||||
}
|
|
||||||
if (paramNames == null) {
|
if (paramNames == null) {
|
||||||
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
|
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
|
||||||
if (pnd != null) {
|
if (pnd != null) {
|
||||||
@@ -297,17 +289,21 @@ class ConstructorResolver {
|
|||||||
*/
|
*/
|
||||||
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
|
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
|
||||||
Class<?> factoryClass;
|
Class<?> factoryClass;
|
||||||
|
boolean isStatic;
|
||||||
if (mbd.getFactoryBeanName() != null) {
|
if (mbd.getFactoryBeanName() != null) {
|
||||||
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
|
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
|
||||||
|
isStatic = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
factoryClass = mbd.getBeanClass();
|
factoryClass = mbd.getBeanClass();
|
||||||
|
isStatic = true;
|
||||||
}
|
}
|
||||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||||
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
|
||||||
|
Method[] candidates = getCandidateMethods(factoryClass, mbd);
|
||||||
Method uniqueCandidate = null;
|
Method uniqueCandidate = null;
|
||||||
for (Method candidate : candidates) {
|
for (Method candidate : candidates) {
|
||||||
if (mbd.isFactoryMethod(candidate)) {
|
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
|
||||||
if (uniqueCandidate == null) {
|
if (uniqueCandidate == null) {
|
||||||
uniqueCandidate = candidate;
|
uniqueCandidate = candidate;
|
||||||
}
|
}
|
||||||
@@ -322,6 +318,27 @@ class ConstructorResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all candidate methods for the given class, considering
|
||||||
|
* the {@link RootBeanDefinition#isNonPublicAccessAllowed()} flag.
|
||||||
|
* Called as the starting point for factory method determination.
|
||||||
|
*/
|
||||||
|
private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
|
||||||
|
@Override
|
||||||
|
public Method[] run() {
|
||||||
|
return (mbd.isNonPublicAccessAllowed() ?
|
||||||
|
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (mbd.isNonPublicAccessAllowed() ?
|
||||||
|
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate the bean using a named factory method. The method may be static, if the
|
* Instantiate the bean using a named factory method. The method may be static, if the
|
||||||
* bean definition parameter specifies a class, rather than a "factory-bean", or
|
* bean definition parameter specifies a class, rather than a "factory-bean", or
|
||||||
@@ -337,7 +354,9 @@ class ConstructorResolver {
|
|||||||
* method, or {@code null} if none (-> use constructor argument values from bean definition)
|
* method, or {@code null} if none (-> use constructor argument values from bean definition)
|
||||||
* @return a BeanWrapper for the new instance
|
* @return a BeanWrapper for the new instance
|
||||||
*/
|
*/
|
||||||
public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
|
public BeanWrapper instantiateUsingFactoryMethod(
|
||||||
|
final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
|
||||||
|
|
||||||
BeanWrapperImpl bw = new BeanWrapperImpl();
|
BeanWrapperImpl bw = new BeanWrapperImpl();
|
||||||
this.beanFactory.initBeanWrapper(bw);
|
this.beanFactory.initBeanWrapper(bw);
|
||||||
|
|
||||||
@@ -398,28 +417,11 @@ class ConstructorResolver {
|
|||||||
// Need to determine the factory method...
|
// Need to determine the factory method...
|
||||||
// Try all methods with this name to see if they match the given arguments.
|
// Try all methods with this name to see if they match the given arguments.
|
||||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||||
Method[] rawCandidates;
|
|
||||||
|
|
||||||
final Class<?> factoryClazz = factoryClass;
|
|
||||||
if (System.getSecurityManager() != null) {
|
|
||||||
rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
|
|
||||||
@Override
|
|
||||||
public Method[] run() {
|
|
||||||
return (mbd.isNonPublicAccessAllowed() ?
|
|
||||||
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rawCandidates = (mbd.isNonPublicAccessAllowed() ?
|
|
||||||
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
|
||||||
List<Method> candidateSet = new ArrayList<Method>();
|
List<Method> candidateSet = new ArrayList<Method>();
|
||||||
for (Method candidate : rawCandidates) {
|
for (Method candidate : rawCandidates) {
|
||||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
|
||||||
candidate.getName().equals(mbd.getFactoryMethodName()) &&
|
|
||||||
mbd.isFactoryMethod(candidate)) {
|
|
||||||
candidateSet.add(candidate);
|
candidateSet.add(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -880,11 +882,11 @@ class ConstructorResolver {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class to avoid a Java 6 dependency.
|
* Delegate for checking Java 6's {@link ConstructorProperties} annotation.
|
||||||
*/
|
*/
|
||||||
private static class ConstructorPropertiesChecker {
|
private static class ConstructorPropertiesChecker {
|
||||||
|
|
||||||
public static String[] evaluateAnnotation(Constructor<?> candidate, int paramCount) {
|
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
|
||||||
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
|
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
|
||||||
if (cp != null) {
|
if (cp != null) {
|
||||||
String[] names = cp.value();
|
String[] names = cp.value();
|
||||||
|
|||||||
Reference in New Issue
Block a user