Optimize array creation in SpEL ConstructorReference
- Create primitive arrays directly instead of using Array#newInstance. - Replace if-else blocks with enhanced switch statement. Closes gh-30189
This commit is contained in:
parent
ddd6b123bb
commit
47aca90c58
|
|
@ -38,7 +38,6 @@ import org.springframework.expression.spel.CodeFlow;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelEvaluationException;
|
import org.springframework.expression.spel.SpelEvaluationException;
|
||||||
import org.springframework.expression.spel.SpelMessage;
|
import org.springframework.expression.spel.SpelMessage;
|
||||||
import org.springframework.expression.spel.SpelNode;
|
|
||||||
import org.springframework.expression.spel.support.ReflectiveConstructorExecutor;
|
import org.springframework.expression.spel.support.ReflectiveConstructorExecutor;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
@ -60,6 +59,7 @@ import org.springframework.util.Assert;
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
|
* @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ConstructorReference extends SpelNodeImpl {
|
public class ConstructorReference extends SpelNodeImpl {
|
||||||
|
|
@ -332,39 +332,18 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.INITIALIZER_LENGTH_INCORRECT);
|
throw new SpelEvaluationException(getStartPosition(), SpelMessage.INITIALIZER_LENGTH_INCORRECT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Build the array and populate it
|
|
||||||
int arraySize = initializer.getChildCount();
|
newArray = switch (arrayTypeCode) {
|
||||||
newArray = Array.newInstance(componentType, arraySize);
|
case OBJECT -> createReferenceTypeArray(state, typeConverter, initializer.children, componentType);
|
||||||
if (arrayTypeCode == TypeCode.OBJECT) {
|
case BOOLEAN -> createBooleanArray(state, typeConverter, initializer.children);
|
||||||
populateReferenceTypeArray(state, newArray, typeConverter, initializer, componentType);
|
case BYTE -> createByteArray(state, typeConverter, initializer.children);
|
||||||
}
|
case CHAR -> createCharArray(state, typeConverter, initializer.children);
|
||||||
else if (arrayTypeCode == TypeCode.BOOLEAN) {
|
case DOUBLE -> createDoubleArray(state, typeConverter, initializer.children);
|
||||||
populateBooleanArray(state, newArray, typeConverter, initializer);
|
case FLOAT -> createFloatArray(state, typeConverter, initializer.children);
|
||||||
}
|
case INT -> createIntArray(state, typeConverter, initializer.children);
|
||||||
else if (arrayTypeCode == TypeCode.BYTE) {
|
case LONG -> createLongArray(state, typeConverter, initializer.children);
|
||||||
populateByteArray(state, newArray, typeConverter, initializer);
|
case SHORT -> createShortArray(state, typeConverter, initializer.children);
|
||||||
}
|
};
|
||||||
else if (arrayTypeCode == TypeCode.CHAR) {
|
|
||||||
populateCharArray(state, newArray, typeConverter, initializer);
|
|
||||||
}
|
|
||||||
else if (arrayTypeCode == TypeCode.DOUBLE) {
|
|
||||||
populateDoubleArray(state, newArray, typeConverter, initializer);
|
|
||||||
}
|
|
||||||
else if (arrayTypeCode == TypeCode.FLOAT) {
|
|
||||||
populateFloatArray(state, newArray, typeConverter, initializer);
|
|
||||||
}
|
|
||||||
else if (arrayTypeCode == TypeCode.INT) {
|
|
||||||
populateIntArray(state, newArray, typeConverter, initializer);
|
|
||||||
}
|
|
||||||
else if (arrayTypeCode == TypeCode.LONG) {
|
|
||||||
populateLongArray(state, newArray, typeConverter, initializer);
|
|
||||||
}
|
|
||||||
else if (arrayTypeCode == TypeCode.SHORT) {
|
|
||||||
populateShortArray(state, newArray, typeConverter, initializer);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalStateException(arrayTypeCode.name());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new TypedValue(newArray);
|
return new TypedValue(newArray);
|
||||||
}
|
}
|
||||||
|
|
@ -376,97 +355,88 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateReferenceTypeArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private Object createReferenceTypeArray(ExpressionState state,
|
||||||
InlineList initializer, Class<?> componentType) {
|
TypeConverter typeConverter, SpelNodeImpl[] children, Class<?> componentType) {
|
||||||
|
Object[] newArray = (Object[]) Array.newInstance(componentType, children.length);
|
||||||
TypeDescriptor toTypeDescriptor = TypeDescriptor.valueOf(componentType);
|
TypeDescriptor toTypeDescriptor = TypeDescriptor.valueOf(componentType);
|
||||||
Object[] newObjectArray = (Object[]) newArray;
|
for (int i = 0; i < newArray.length; i++) {
|
||||||
for (int i = 0; i < newObjectArray.length; i++) {
|
Object arrayEntry = children[i].getValue(state);
|
||||||
SpelNode elementNode = initializer.getChild(i);
|
newArray[i] = typeConverter.convertValue(arrayEntry,
|
||||||
Object arrayEntry = elementNode.getValue(state);
|
|
||||||
newObjectArray[i] = typeConverter.convertValue(arrayEntry,
|
|
||||||
TypeDescriptor.forObject(arrayEntry), toTypeDescriptor);
|
TypeDescriptor.forObject(arrayEntry), toTypeDescriptor);
|
||||||
}
|
}
|
||||||
|
return newArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateByteArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private byte[] createByteArray(ExpressionState state, TypeConverter converter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
byte[] byteArray = new byte[children.length];
|
||||||
|
for (int i = 0; i < byteArray.length; i++) {
|
||||||
byte[] newByteArray = (byte[]) newArray;
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
for (int i = 0; i < newByteArray.length; i++) {
|
byteArray[i] = ExpressionUtils.toByte(converter, typedValue);
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
|
||||||
newByteArray[i] = ExpressionUtils.toByte(typeConverter, typedValue);
|
|
||||||
}
|
}
|
||||||
|
return byteArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateFloatArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private float[] createFloatArray(ExpressionState state, TypeConverter typeConverter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
float[] floatArray = new float[children.length];
|
||||||
|
for (int i = 0; i < floatArray.length; i++) {
|
||||||
float[] newFloatArray = (float[]) newArray;
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
for (int i = 0; i < newFloatArray.length; i++) {
|
floatArray[i] = ExpressionUtils.toFloat(typeConverter, typedValue);
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
|
||||||
newFloatArray[i] = ExpressionUtils.toFloat(typeConverter, typedValue);
|
|
||||||
}
|
}
|
||||||
|
return floatArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateDoubleArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private double[] createDoubleArray(ExpressionState state, TypeConverter typeConverter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
double[] doubleArray = new double[children.length];
|
||||||
|
for (int i = 0; i < doubleArray.length; i++) {
|
||||||
double[] newDoubleArray = (double[]) newArray;
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
for (int i = 0; i < newDoubleArray.length; i++) {
|
doubleArray[i] = ExpressionUtils.toDouble(typeConverter, typedValue);
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
|
||||||
newDoubleArray[i] = ExpressionUtils.toDouble(typeConverter, typedValue);
|
|
||||||
}
|
}
|
||||||
|
return doubleArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateShortArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private short[] createShortArray(ExpressionState state, TypeConverter typeConverter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
short[] shortArray = new short[children.length];
|
||||||
|
for (int i = 0; i < shortArray.length; i++) {
|
||||||
short[] newShortArray = (short[]) newArray;
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
for (int i = 0; i < newShortArray.length; i++) {
|
shortArray[i] = ExpressionUtils.toShort(typeConverter, typedValue);
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
|
||||||
newShortArray[i] = ExpressionUtils.toShort(typeConverter, typedValue);
|
|
||||||
}
|
}
|
||||||
|
return shortArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateLongArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private long[] createLongArray(ExpressionState state, TypeConverter converter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
long[] longArray = new long[children.length];
|
||||||
|
for (int i = 0; i < longArray.length; i++) {
|
||||||
long[] newLongArray = (long[]) newArray;
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
for (int i = 0; i < newLongArray.length; i++) {
|
longArray[i] = ExpressionUtils.toLong(converter, typedValue);
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
|
||||||
newLongArray[i] = ExpressionUtils.toLong(typeConverter, typedValue);
|
|
||||||
}
|
}
|
||||||
|
return longArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateCharArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private char[] createCharArray(ExpressionState state, TypeConverter typeConverter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
char[] newCharArray = new char[children.length];
|
||||||
|
|
||||||
char[] newCharArray = (char[]) newArray;
|
|
||||||
for (int i = 0; i < newCharArray.length; i++) {
|
for (int i = 0; i < newCharArray.length; i++) {
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
newCharArray[i] = ExpressionUtils.toChar(typeConverter, typedValue);
|
newCharArray[i] = ExpressionUtils.toChar(typeConverter, typedValue);
|
||||||
}
|
}
|
||||||
|
return newCharArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateBooleanArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private boolean[] createBooleanArray(ExpressionState state, TypeConverter typeConverter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
boolean[] newBooleanArray = new boolean[children.length];
|
||||||
|
|
||||||
boolean[] newBooleanArray = (boolean[]) newArray;
|
|
||||||
for (int i = 0; i < newBooleanArray.length; i++) {
|
for (int i = 0; i < newBooleanArray.length; i++) {
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
newBooleanArray[i] = ExpressionUtils.toBoolean(typeConverter, typedValue);
|
newBooleanArray[i] = ExpressionUtils.toBoolean(typeConverter, typedValue);
|
||||||
}
|
}
|
||||||
|
return newBooleanArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateIntArray(ExpressionState state, Object newArray, TypeConverter typeConverter,
|
private int[] createIntArray(ExpressionState state, TypeConverter typeConverter, SpelNodeImpl[] children) {
|
||||||
InlineList initializer) {
|
int[] intArray = new int[children.length];
|
||||||
|
for (int i = 0; i < intArray.length; i++) {
|
||||||
int[] newIntArray = (int[]) newArray;
|
TypedValue typedValue = children[i].getTypedValue(state);
|
||||||
for (int i = 0; i < newIntArray.length; i++) {
|
intArray[i] = ExpressionUtils.toInt(typeConverter, typedValue);
|
||||||
TypedValue typedValue = initializer.getChild(i).getTypedValue(state);
|
|
||||||
newIntArray[i] = ExpressionUtils.toInt(typeConverter, typedValue);
|
|
||||||
}
|
}
|
||||||
|
return intArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasInitializer() {
|
private boolean hasInitializer() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue