如何使用 Spring 表达式语言将没有构造函数的对象添加到列表中
How to add an object without a constructor to a list using Spring Expression Language
我想使用 Spring 表达式语言将 BigDecimal
添加到列表中。
public class SpelTest {
public List<BigDecimal> values;
StandardEvaluationContext context;
SpelExpressionParser parser;
@Before
public void setup() {
values = new ArrayList<>();
context = new StandardEvaluationContext(this);
parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
}
@Test
public void shouldChangeValue() {
values.add(BigDecimal.ONE);
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // passes
}
@Test
public void shouldAddValue() {
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // fails
}
}
更改第一个条目通过但添加条目失败
Caused by: java.lang.NoSuchMethodException: java.math.BigDecimal.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3349)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
at org.springframework.util.ReflectionUtils.accessibleConstructor(ReflectionUtils.java:185)
at org.springframework.expression.spel.ast.Indexer$CollectionIndexingValueRef.growCollectionIfNecessary(Indexer.java:715)
... 55 more
不确定为什么当列表为空时 SpEL 无法正确初始化 BigDecimal
。令人惊讶的是,我没有发现任何关于这个问题的信息。
感谢您的帮助!
问题是您在 SpelParserConfiguraion
上激活了 autoGrowCollections
。
因此,如果您尝试使用索引运算符 []
访问集合中不存在的元素,它会尝试使用默认构造函数创建元素。 BigDecimal
没有默认构造函数,因此失败。
您可以做的是在 SpEL 本身中创建对象。例如:
@Test
public void shouldAddValue() {
parser.parseExpression("values.add(0, new java.math.BigDecimal(\"123.4\"))").getValue(context);
assertThat(values.size() > 0);
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4));
}
或者您可以创建 BigDecimal
的子class 具有默认构造函数并使用此 class.
您可以通过设置整个列表而不是单个(未初始化的)元素来避免此问题。而不是
parser.parseExpression("values[0]").setValue(context, "123.4");
使用:
parser.parseExpression("values").setValue(context, "123.4");
这也适用于多个元素,非常简洁:
parser.parseExpression("values").setValue(context, "123.4, 456.7");
正如@Nirud 指出的那样,问题是 BigDecimal
没有默认构造函数。当没有默认构造函数时,我扩展了 SpEL 以将 null
添加到列表中。请参阅此拉取请求:https://github.com/spring-projects/spring-framework/pull/25367
我想使用 Spring 表达式语言将 BigDecimal
添加到列表中。
public class SpelTest {
public List<BigDecimal> values;
StandardEvaluationContext context;
SpelExpressionParser parser;
@Before
public void setup() {
values = new ArrayList<>();
context = new StandardEvaluationContext(this);
parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
}
@Test
public void shouldChangeValue() {
values.add(BigDecimal.ONE);
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // passes
}
@Test
public void shouldAddValue() {
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // fails
}
}
更改第一个条目通过但添加条目失败
Caused by: java.lang.NoSuchMethodException: java.math.BigDecimal.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3349)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
at org.springframework.util.ReflectionUtils.accessibleConstructor(ReflectionUtils.java:185)
at org.springframework.expression.spel.ast.Indexer$CollectionIndexingValueRef.growCollectionIfNecessary(Indexer.java:715)
... 55 more
不确定为什么当列表为空时 SpEL 无法正确初始化 BigDecimal
。令人惊讶的是,我没有发现任何关于这个问题的信息。
感谢您的帮助!
问题是您在 SpelParserConfiguraion
上激活了 autoGrowCollections
。
因此,如果您尝试使用索引运算符 []
访问集合中不存在的元素,它会尝试使用默认构造函数创建元素。 BigDecimal
没有默认构造函数,因此失败。
您可以做的是在 SpEL 本身中创建对象。例如:
@Test
public void shouldAddValue() {
parser.parseExpression("values.add(0, new java.math.BigDecimal(\"123.4\"))").getValue(context);
assertThat(values.size() > 0);
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4));
}
或者您可以创建 BigDecimal
的子class 具有默认构造函数并使用此 class.
您可以通过设置整个列表而不是单个(未初始化的)元素来避免此问题。而不是
parser.parseExpression("values[0]").setValue(context, "123.4");
使用:
parser.parseExpression("values").setValue(context, "123.4");
这也适用于多个元素,非常简洁:
parser.parseExpression("values").setValue(context, "123.4, 456.7");
正如@Nirud 指出的那样,问题是 BigDecimal
没有默认构造函数。当没有默认构造函数时,我扩展了 SpEL 以将 null
添加到列表中。请参阅此拉取请求:https://github.com/spring-projects/spring-framework/pull/25367