Consistently use constructor-based instantiation instead of Class.newInstance / BeanUtils.instantiate
Issue: SPR-14486
This commit is contained in:
@@ -38,6 +38,7 @@ import java.util.TreeSet;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Factory for collections that is aware of Java 5, Java 6, and Spring
|
||||
@@ -201,9 +202,9 @@ public abstract class CollectionFactory {
|
||||
throw new IllegalArgumentException("Unsupported Collection type: " + collectionType.getName());
|
||||
}
|
||||
try {
|
||||
return (Collection<E>) collectionType.newInstance();
|
||||
return (Collection<E>) ReflectionUtils.accessibleConstructor(collectionType).newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate Collection type: " + collectionType.getName(), ex);
|
||||
}
|
||||
@@ -316,9 +317,9 @@ public abstract class CollectionFactory {
|
||||
throw new IllegalArgumentException("Unsupported Map type: " + mapType.getName());
|
||||
}
|
||||
try {
|
||||
return (Map<K, V>) mapType.newInstance();
|
||||
return (Map<K, V>) ReflectionUtils.accessibleConstructor(mapType).newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Could not instantiate Map type: " + mapType.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -101,7 +101,7 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
|
||||
}
|
||||
}
|
||||
try {
|
||||
return Proxy.getProxyClass(this.classLoader, resolvedInterfaces);
|
||||
return ClassUtils.createCompositeInterface(resolvedInterfaces, this.classLoader);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new ClassNotFoundException(null, ex);
|
||||
@@ -117,7 +117,7 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
resolvedInterfaces[i] = resolveFallbackIfPossible(interfaces[i], ex);
|
||||
}
|
||||
return Proxy.getProxyClass(getFallbackClassLoader(), resolvedInterfaces);
|
||||
return ClassUtils.createCompositeInterface(resolvedInterfaces, getFallbackClassLoader());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.core.io.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -134,12 +133,10 @@ public abstract class SpringFactoriesLoader {
|
||||
throw new IllegalArgumentException(
|
||||
"Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]");
|
||||
}
|
||||
Constructor<?> constructor = instanceClass.getDeclaredConstructor();
|
||||
ReflectionUtils.makeAccessible(constructor);
|
||||
return (T) constructor.newInstance();
|
||||
return (T) ReflectionUtils.accessibleConstructor(instanceClass).newInstance();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Cannot instantiate factory class: " + factoryClass.getName(), ex);
|
||||
throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -264,13 +265,16 @@ public class AutoPopulatingList<E> implements List<E>, Serializable {
|
||||
public ElementInstantiationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public ElementInstantiationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reflective implementation of the ElementFactory interface,
|
||||
* using {@code Class.newInstance()} on a given element class.
|
||||
* @see Class#newInstance()
|
||||
* Reflective implementation of the ElementFactory interface, using
|
||||
* {@code Class.getDeclaredConstructor().newInstance()} on a given element class.
|
||||
*/
|
||||
private static class ReflectiveElementFactory<E> implements ElementFactory<E>, Serializable {
|
||||
|
||||
@@ -286,15 +290,23 @@ public class AutoPopulatingList<E> implements List<E>, Serializable {
|
||||
@Override
|
||||
public E createElement(int index) {
|
||||
try {
|
||||
return this.elementClass.newInstance();
|
||||
return ReflectionUtils.accessibleConstructor(this.elementClass).newInstance();
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new ElementInstantiationException(
|
||||
"No default constructor on element class: " + this.elementClass.getName(), ex);
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new ElementInstantiationException("Unable to instantiate element class [" +
|
||||
this.elementClass.getName() + "]. Root cause is " + ex);
|
||||
throw new ElementInstantiationException(
|
||||
"Unable to instantiate element class: " + this.elementClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new ElementInstantiationException("Cannot access element class [" +
|
||||
this.elementClass.getName() + "]. Root cause is " + ex);
|
||||
throw new ElementInstantiationException(
|
||||
"Could not access element constructor: " + this.elementClass.getName(), ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new ElementInstantiationException(
|
||||
"Failed to invoke element constructor: " + this.elementClass.getName(), ex.getTargetException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1156,6 +1156,7 @@ public abstract class ClassUtils {
|
||||
* @return the merged interface as Class
|
||||
* @see java.lang.reflect.Proxy#getProxyClass
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Class<?> createCompositeInterface(Class<?>[] interfaces, ClassLoader classLoader) {
|
||||
Assert.notEmpty(interfaces, "Interfaces must not be empty");
|
||||
Assert.notNull(classLoader, "ClassLoader must not be null");
|
||||
|
||||
@@ -476,6 +476,22 @@ public abstract class ReflectionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain an accessible constructor for the given class and parameters.
|
||||
* @param clazz the clazz to check
|
||||
* @param parameterTypes the parameter types of the desired constructor
|
||||
* @return the constructor reference
|
||||
* @throws NoSuchMethodException if no such constructor exists
|
||||
* @since 5.0
|
||||
*/
|
||||
public static <T> Constructor<T> accessibleConstructor(Class<T> clazz, Class<?>... parameterTypes)
|
||||
throws NoSuchMethodException {
|
||||
|
||||
Constructor<T> ctor = clazz.getDeclaredConstructor(parameterTypes);
|
||||
makeAccessible(ctor);
|
||||
return ctor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the given callback operation on all matching methods of the given
|
||||
* class, as locally declared or equivalent thereof (such as default methods
|
||||
|
||||
Reference in New Issue
Block a user