Merge branch '5.2.x'
# Conflicts: # spring-expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java
This commit is contained in:
commit
9d7849c539
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -348,8 +348,8 @@ public class MethodReference extends SpelNodeImpl {
|
||||||
|
|
||||||
generateCodeForArguments(mv, cf, method, this.children);
|
generateCodeForArguments(mv, cf, method, this.children);
|
||||||
mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : (method.isDefault() ? INVOKEINTERFACE : INVOKEVIRTUAL)),
|
mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : (method.isDefault() ? INVOKEINTERFACE : INVOKEVIRTUAL)),
|
||||||
classDesc, method.getName(),
|
classDesc, method.getName(), CodeFlow.createSignatureDescriptor(method),
|
||||||
CodeFlow.createSignatureDescriptor(method), method.getDeclaringClass().isInterface());
|
method.getDeclaringClass().isInterface());
|
||||||
cf.pushDescriptor(this.exitTypeDescriptor);
|
cf.pushDescriptor(this.exitTypeDescriptor);
|
||||||
|
|
||||||
if (this.originalPrimitiveExitTypeDescriptor != null) {
|
if (this.originalPrimitiveExitTypeDescriptor != null) {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*/
|
*/
|
||||||
class SpelCompilerTests {
|
class SpelCompilerTests {
|
||||||
|
|
||||||
@Test // gh-24357
|
@Test // gh-24357
|
||||||
void expressionCompilesWhenMethodComesFromPublicInterface() {
|
void expressionCompilesWhenMethodComesFromPublicInterface() {
|
||||||
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);
|
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);
|
||||||
SpelExpressionParser parser = new SpelExpressionParser(config);
|
SpelExpressionParser parser = new SpelExpressionParser(config);
|
||||||
|
|
@ -50,6 +50,31 @@ class SpelCompilerTests {
|
||||||
IntStream.rangeClosed(1, 5).forEach(i -> assertThat(expression.getValue(component)).isEqualTo(42));
|
IntStream.rangeClosed(1, 5).forEach(i -> assertThat(expression.getValue(component)).isEqualTo(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // gh-25706
|
||||||
|
void defaultMethodInvocation() {
|
||||||
|
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);
|
||||||
|
SpelExpressionParser parser = new SpelExpressionParser(config);
|
||||||
|
|
||||||
|
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||||
|
Item item = new Item();
|
||||||
|
context.setRootObject(item);
|
||||||
|
|
||||||
|
Expression expression = parser.parseExpression("#root.isEditable2()");
|
||||||
|
assertThat(SpelCompiler.compile(expression)).isFalse();
|
||||||
|
assertThat(expression.getValue(context)).isEqualTo(false);
|
||||||
|
assertThat(SpelCompiler.compile(expression)).isTrue();
|
||||||
|
SpelCompilationCoverageTests.assertIsCompiled(expression);
|
||||||
|
assertThat(expression.getValue(context)).isEqualTo(false);
|
||||||
|
|
||||||
|
context.setVariable("user", new User());
|
||||||
|
expression = parser.parseExpression("#root.isEditable(#user)");
|
||||||
|
assertThat(SpelCompiler.compile(expression)).isFalse();
|
||||||
|
assertThat(expression.getValue(context)).isEqualTo(true);
|
||||||
|
assertThat(SpelCompiler.compile(expression)).isTrue();
|
||||||
|
SpelCompilationCoverageTests.assertIsCompiled(expression);
|
||||||
|
assertThat(expression.getValue(context)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static class OrderedComponent implements Ordered {
|
static class OrderedComponent implements Ordered {
|
||||||
|
|
||||||
|
|
@ -114,4 +139,40 @@ class SpelCompilerTests {
|
||||||
boolean hasSomeProperty();
|
boolean hasSomeProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class User {
|
||||||
|
|
||||||
|
boolean isAdmin() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Item implements Editable {
|
||||||
|
|
||||||
|
// some fields
|
||||||
|
private String someField = "";
|
||||||
|
|
||||||
|
// some getters and setters
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSomeProperty() {
|
||||||
|
return someField != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface Editable {
|
||||||
|
|
||||||
|
default boolean isEditable(User user) {
|
||||||
|
return user.isAdmin() && hasSomeProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isEditable2() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasSomeProperty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,12 +66,11 @@ public abstract class StatementCreatorUtils {
|
||||||
* completely, i.e. to never even attempt to retrieve {@link PreparedStatement#getParameterMetaData()}
|
* completely, i.e. to never even attempt to retrieve {@link PreparedStatement#getParameterMetaData()}
|
||||||
* for {@link StatementCreatorUtils#setNull} calls.
|
* for {@link StatementCreatorUtils#setNull} calls.
|
||||||
* <p>The default is "false", trying {@code getParameterType} calls first and falling back to
|
* <p>The default is "false", trying {@code getParameterType} calls first and falling back to
|
||||||
* {@link PreparedStatement#setNull} / {@link PreparedStatement#setObject} calls based on well-known
|
* {@link PreparedStatement#setNull} / {@link PreparedStatement#setObject} calls based on
|
||||||
* behavior of common databases. Spring records JDBC drivers with non-working {@code getParameterType}
|
* well-known behavior of common databases.
|
||||||
* implementations and won't attempt to call that method for that driver again, always falling back.
|
* <p>Consider switching this flag to "true" if you experience misbehavior at runtime,
|
||||||
* <p>Consider switching this flag to "true" if you experience misbehavior at runtime, e.g. with
|
* e.g. with connection pool issues in case of an exception thrown from {@code getParameterType}
|
||||||
* a connection pool setting back the {@link PreparedStatement} instance in case of an exception
|
* (as reported on JBoss AS 7) or in case of performance problems (as reported on PostgreSQL).
|
||||||
* thrown from {@code getParameterType} (as reported on JBoss AS 7).
|
|
||||||
*/
|
*/
|
||||||
public static final String IGNORE_GETPARAMETERTYPE_PROPERTY_NAME = "spring.jdbc.getParameterType.ignore";
|
public static final String IGNORE_GETPARAMETERTYPE_PROPERTY_NAME = "spring.jdbc.getParameterType.ignore";
|
||||||
|
|
||||||
|
|
@ -266,7 +265,7 @@ public abstract class StatementCreatorUtils {
|
||||||
}
|
}
|
||||||
else if (databaseProductName.startsWith("DB2") ||
|
else if (databaseProductName.startsWith("DB2") ||
|
||||||
jdbcDriverName.startsWith("jConnect") ||
|
jdbcDriverName.startsWith("jConnect") ||
|
||||||
jdbcDriverName.startsWith("SQLServer")||
|
jdbcDriverName.startsWith("SQLServer") ||
|
||||||
jdbcDriverName.startsWith("Apache Derby")) {
|
jdbcDriverName.startsWith("Apache Derby")) {
|
||||||
sqlTypeToUse = Types.VARCHAR;
|
sqlTypeToUse = Types.VARCHAR;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ public class CallMetaDataContext {
|
||||||
logger.debug("Using declared out parameter '" + paramName +
|
logger.debug("Using declared out parameter '" + paramName +
|
||||||
"' for function return value");
|
"' for function return value");
|
||||||
}
|
}
|
||||||
setFunctionReturnName(paramName);
|
this.actualFunctionReturnName = paramName;
|
||||||
returnDeclared = true;
|
returnDeclared = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -393,8 +393,8 @@ public class CallMetaDataContext {
|
||||||
"Unable to locate declared parameter for function return value - " +
|
"Unable to locate declared parameter for function return value - " +
|
||||||
" add an SqlOutParameter with name '" + getFunctionReturnName() + "'");
|
" add an SqlOutParameter with name '" + getFunctionReturnName() + "'");
|
||||||
}
|
}
|
||||||
else if (paramName != null) {
|
else {
|
||||||
setFunctionReturnName(paramName);
|
this.actualFunctionReturnName = param.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -422,7 +422,7 @@ public class CallMetaDataContext {
|
||||||
(StringUtils.hasLength(paramNameToUse) ? paramNameToUse : getFunctionReturnName());
|
(StringUtils.hasLength(paramNameToUse) ? paramNameToUse : getFunctionReturnName());
|
||||||
workParams.add(provider.createDefaultOutParameter(returnNameToUse, meta));
|
workParams.add(provider.createDefaultOutParameter(returnNameToUse, meta));
|
||||||
if (isFunction()) {
|
if (isFunction()) {
|
||||||
setFunctionReturnName(returnNameToUse);
|
this.actualFunctionReturnName = returnNameToUse;
|
||||||
outParamNames.add(returnNameToUse);
|
outParamNames.add(returnNameToUse);
|
||||||
}
|
}
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
|
|
|
||||||
|
|
@ -4452,7 +4452,7 @@ While this usually works well, there is a potential for issues (for example, wit
|
||||||
case, which can be expensive with your JDBC driver. You should use a recent driver
|
case, which can be expensive with your JDBC driver. You should use a recent driver
|
||||||
version and consider setting the `spring.jdbc.getParameterType.ignore` property to `true`
|
version and consider setting the `spring.jdbc.getParameterType.ignore` property to `true`
|
||||||
(as a JVM system property or in a `spring.properties` file in the root of your classpath)
|
(as a JVM system property or in a `spring.properties` file in the root of your classpath)
|
||||||
if you encounter a performance issue -- for example, as reported on Oracle 12c (SPR-16139).
|
if you encounter a performance issue (as reported on Oracle 12c, JBoss and PostgreSQL).
|
||||||
|
|
||||||
Alternatively, you might consider specifying the corresponding JDBC types explicitly,
|
Alternatively, you might consider specifying the corresponding JDBC types explicitly,
|
||||||
either through a 'BatchPreparedStatementSetter' (as shown earlier), through an explicit type
|
either through a 'BatchPreparedStatementSetter' (as shown earlier), through an explicit type
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue