Browse Source

Consistently use DefaultParameterNameDiscoverer.getSharedInstance()

This includes MethodParameter resolving getParameterName() by default now.
initParameterNameDiscovery(null) can be used to suppress such resolution.

Closes gh-36024
pull/34537/merge
Juergen Hoeller 21 hours ago
parent
commit
c813577908
  1. 5
      spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java
  2. 7
      spring-beans/src/main/java/org/springframework/beans/BeanUtils.java
  3. 5
      spring-context/src/main/java/org/springframework/cache/interceptor/CacheEvaluationContextFactory.java
  4. 4
      spring-context/src/main/java/org/springframework/context/expression/CachedExpressionEvaluator.java
  5. 7
      spring-context/src/main/java/org/springframework/jmx/export/assembler/AbstractReflectiveMBeanInfoAssembler.java
  6. 2
      spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationAdapter.java
  7. 25
      spring-core/src/main/java/org/springframework/core/DefaultParameterNameDiscoverer.java
  8. 7
      spring-core/src/main/java/org/springframework/core/MethodParameter.java
  9. 9
      spring-core/src/test/java/org/springframework/core/MethodParameterTests.java
  10. 3
      spring-core/src/test/kotlin/org/springframework/core/MethodParameterKotlinTests.kt
  11. 2
      spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java
  12. 2
      spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/InvocableHandlerMethod.java
  13. 3
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceMethod.java
  14. 2
      spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java
  15. 3
      spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java
  16. 2
      spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java
  17. 7
      spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java
  18. 5
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java
  19. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java

5
spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java

@ -29,7 +29,6 @@ import org.jspecify.annotations.Nullable; @@ -29,7 +29,6 @@ import org.jspecify.annotations.Nullable;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.util.Assert;
/**
@ -51,8 +50,6 @@ import org.springframework.util.Assert; @@ -51,8 +50,6 @@ import org.springframework.util.Assert;
*/
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private final ProxyMethodInvocation methodInvocation;
private @Nullable Object @Nullable [] args;
@ -217,7 +214,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, @@ -217,7 +214,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
public @Nullable String @Nullable [] getParameterNames() {
@Nullable String[] parameterNames = this.parameterNames;
if (parameterNames == null) {
parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
parameterNames = DefaultParameterNameDiscoverer.getSharedInstance().getParameterNames(getMethod());
this.parameterNames = parameterNames;
}
return parameterNames;

7
spring-beans/src/main/java/org/springframework/beans/BeanUtils.java

@ -45,7 +45,6 @@ import org.jspecify.annotations.Nullable; @@ -45,7 +45,6 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.ResolvableType;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -72,9 +71,6 @@ import org.springframework.util.StringUtils; @@ -72,9 +71,6 @@ import org.springframework.util.StringUtils;
*/
public abstract class BeanUtils {
private static final ParameterNameDiscoverer parameterNameDiscoverer =
new DefaultParameterNameDiscoverer();
private static final Set<Class<?>> unknownEditorTypes =
Collections.newSetFromMap(new ConcurrentReferenceHashMap<>(64));
@ -659,7 +655,8 @@ public abstract class BeanUtils { @@ -659,7 +655,8 @@ public abstract class BeanUtils {
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public static @Nullable String[] getParameterNames(Constructor<?> ctor) {
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
@Nullable String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
@Nullable String[] paramNames = (cp != null ? cp.value() :
DefaultParameterNameDiscoverer.getSharedInstance().getParameterNames(ctor));
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
int parameterCount = (KOTLIN_REFLECT_PRESENT && KotlinDelegate.hasDefaultConstructorMarker(ctor) ?
ctor.getParameterCount() - 1 : ctor.getParameterCount());

5
spring-context/src/main/java/org/springframework/cache/interceptor/CacheEvaluationContextFactory.java vendored

@ -39,21 +39,24 @@ class CacheEvaluationContextFactory { @@ -39,21 +39,24 @@ class CacheEvaluationContextFactory {
private @Nullable Supplier<ParameterNameDiscoverer> parameterNameDiscoverer;
CacheEvaluationContextFactory(StandardEvaluationContext originalContext) {
this.originalContext = originalContext;
}
public void setParameterNameDiscoverer(Supplier<ParameterNameDiscoverer> parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
}
public ParameterNameDiscoverer getParameterNameDiscoverer() {
if (this.parameterNameDiscoverer == null) {
this.parameterNameDiscoverer = SingletonSupplier.of(new DefaultParameterNameDiscoverer());
this.parameterNameDiscoverer = SingletonSupplier.of(DefaultParameterNameDiscoverer.getSharedInstance());
}
return this.parameterNameDiscoverer.get();
}
/**
* Creates a {@link CacheEvaluationContext} for the specified operation.
* @param rootObject the {@code root} object to use for the context

4
spring-context/src/main/java/org/springframework/context/expression/CachedExpressionEvaluator.java

@ -38,8 +38,6 @@ public abstract class CachedExpressionEvaluator { @@ -38,8 +38,6 @@ public abstract class CachedExpressionEvaluator {
private final SpelExpressionParser parser;
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
/**
* Create a new instance with the default {@link SpelExpressionParser}.
@ -69,7 +67,7 @@ public abstract class CachedExpressionEvaluator { @@ -69,7 +67,7 @@ public abstract class CachedExpressionEvaluator {
* @since 4.3
*/
protected ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
return DefaultParameterNameDiscoverer.getSharedInstance();
}
/**

7
spring-context/src/main/java/org/springframework/jmx/export/assembler/AbstractReflectiveMBeanInfoAssembler.java

@ -183,7 +183,8 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean @@ -183,7 +183,8 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
private boolean exposeClassDescriptor = false;
private @Nullable ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private @Nullable ParameterNameDiscoverer parameterNameDiscoverer =
DefaultParameterNameDiscoverer.getSharedInstance();
/**
@ -507,8 +508,8 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean @@ -507,8 +508,8 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
* @return the {@code MBeanParameterInfo} array
*/
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
ParameterNameDiscoverer paramNameDiscoverer = getParameterNameDiscoverer();
@Nullable String[] paramNames = (paramNameDiscoverer != null ? paramNameDiscoverer.getParameterNames(method) : null);
ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
@Nullable String[] paramNames = (pnd != null ? pnd.getParameterNames(method) : null);
if (paramNames == null) {
return new MBeanParameterInfo[0];
}

2
spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationAdapter.java

@ -87,7 +87,7 @@ public class MethodValidationAdapter implements MethodValidator { @@ -87,7 +87,7 @@ public class MethodValidationAdapter implements MethodValidator {
private MessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
private ObjectNameResolver objectNameResolver = defaultObjectNameResolver;

25
spring-core/src/main/java/org/springframework/core/DefaultParameterNameDiscoverer.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.core;
import org.jspecify.annotations.Nullable;
/**
* Default implementation of the {@link ParameterNameDiscoverer} strategy interface,
* delegating to the Java 8 standard reflection mechanism.
@ -37,6 +39,8 @@ public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDisc @@ -37,6 +39,8 @@ public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDisc
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
private static volatile @Nullable DefaultParameterNameDiscoverer sharedInstance;
public DefaultParameterNameDiscoverer() {
if (KOTLIN_REFLECT_PRESENT) {
@ -47,4 +51,25 @@ public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDisc @@ -47,4 +51,25 @@ public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDisc
addDiscoverer(new StandardReflectionParameterNameDiscoverer());
}
/**
* Return a shared default {@code ParameterNameDiscoverer} instance,
* lazily building it once needed.
* @return the shared {@code ParameterNameDiscoverer} instance
* @since 7.0.3
*/
public static ParameterNameDiscoverer getSharedInstance() {
DefaultParameterNameDiscoverer pnd = sharedInstance;
if (pnd == null) {
synchronized (DefaultParameterNameDiscoverer.class) {
pnd = sharedInstance;
if (pnd == null) {
pnd = new DefaultParameterNameDiscoverer();
sharedInstance = pnd;
}
}
}
return pnd;
}
}

7
spring-core/src/main/java/org/springframework/core/MethodParameter.java

@ -89,7 +89,8 @@ public class MethodParameter { @@ -89,7 +89,8 @@ public class MethodParameter {
private volatile Annotation @Nullable [] parameterAnnotations;
private volatile @Nullable ParameterNameDiscoverer parameterNameDiscoverer;
private volatile @Nullable ParameterNameDiscoverer parameterNameDiscoverer =
DefaultParameterNameDiscoverer.getSharedInstance();
volatile @Nullable String parameterName;
@ -667,6 +668,10 @@ public class MethodParameter { @@ -667,6 +668,10 @@ public class MethodParameter {
* <p>This method does not actually try to retrieve the parameter name at
* this point; it just allows discovery to happen when the application calls
* {@link #getParameterName()} (if ever).
* <p>Note: As of 7.0.3, a default parameter name discoverer is available.
* This init method can be used to override the default discoverer or to
* suppress discovery (passing {@code null}).
* @see DefaultParameterNameDiscoverer#getSharedInstance()
*/
public void initParameterNameDiscovery(@Nullable ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;

9
spring-core/src/test/java/org/springframework/core/MethodParameterTests.java

@ -252,6 +252,12 @@ class MethodParameterTests { @@ -252,6 +252,12 @@ class MethodParameterTests {
assertThat(m3.getTypeIndexForCurrentLevel()).isEqualTo(3);
}
@Test
void parameterNames() {
assertThat(stringParameter.getParameterName()).isEqualTo("str");
assertThat(longParameter.getParameterName()).isEqualTo("lng");
}
@Test
void jspecifyNullableParameter() {
assertThat(jspecifyNullableParameter.isOptional()).isTrue();
@ -272,7 +278,8 @@ class MethodParameterTests { @@ -272,7 +278,8 @@ class MethodParameterTests {
assertThat(springNonNullParameter.isOptional()).isFalse();
}
public int method(String p1, long p2) {
public int method(String str, long lng) {
return 42;
}

3
spring-core/src/test/kotlin/org/springframework/core/MethodParameterKotlinTests.kt

@ -117,21 +117,18 @@ class MethodParameterKotlinTests { @@ -117,21 +117,18 @@ class MethodParameterKotlinTests {
@Test
fun `Parameter name for regular function`() {
val methodParameter = returnMethodParameter("nullable", 0)
methodParameter.initParameterNameDiscovery(KotlinReflectionParameterNameDiscoverer())
assertThat(methodParameter.getParameterName()).isEqualTo("nullable")
}
@Test
fun `Parameter name for suspending function`() {
val methodParameter = returnMethodParameter("suspendFun", 0)
methodParameter.initParameterNameDiscovery(KotlinReflectionParameterNameDiscoverer())
assertThat(methodParameter.getParameterName()).isEqualTo("p1")
}
@Test
fun `Continuation parameter name for suspending function`() {
val methodParameter = returnMethodParameter("suspendFun", 1)
methodParameter.initParameterNameDiscovery(KotlinReflectionParameterNameDiscoverer())
assertThat(methodParameter.getParameterName()).isNull()
}

2
spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java

@ -47,7 +47,7 @@ public class InvocableHandlerMethod extends HandlerMethod { @@ -47,7 +47,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
/**

2
spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/InvocableHandlerMethod.java

@ -55,7 +55,7 @@ public class InvocableHandlerMethod extends HandlerMethod { @@ -55,7 +55,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
private final HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();

3
spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceMethod.java

@ -30,7 +30,6 @@ import org.reactivestreams.Publisher; @@ -30,7 +30,6 @@ import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterizedTypeReference;
@ -90,11 +89,9 @@ final class RSocketServiceMethod { @@ -90,11 +89,9 @@ final class RSocketServiceMethod {
count -= 1;
}
DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
MethodParameter[] parameters = new MethodParameter[count];
for (int i = 0; i < count; i++) {
parameters[i] = new SynthesizingMethodParameter(method, i);
parameters[i].initParameterNameDiscovery(nameDiscoverer);
}
return parameters;
}

2
spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java

@ -71,7 +71,7 @@ public class InvocableHandlerMethod extends HandlerMethod { @@ -71,7 +71,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
private @Nullable WebDataBinderFactory dataBinderFactory;

3
spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java

@ -30,7 +30,6 @@ import org.reactivestreams.Publisher; @@ -30,7 +30,6 @@ import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterizedTypeReference;
@ -115,11 +114,9 @@ final class HttpServiceMethod { @@ -115,11 +114,9 @@ final class HttpServiceMethod {
count -= 1;
}
DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
MethodParameter[] parameters = new MethodParameter[count];
for (int i = 0; i < count; i++) {
parameters[i] = new SynthesizingMethodParameter(method, i);
parameters[i].initParameterNameDiscovery(nameDiscoverer);
}
return parameters;
}

2
spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java

@ -90,7 +90,7 @@ public class InvocableHandlerMethod extends HandlerMethod { @@ -90,7 +90,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
private final HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();

7
spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java

@ -605,14 +605,15 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap @@ -605,14 +605,15 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
validateMethodMapping(handlerMethod, mapping);
Set<String> directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping);
Set<String> directPaths = getDirectPaths(mapping);
for (String path : directPaths) {
this.pathLookup.add(path, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
HandlerMethodMappingNamingStrategy<T> namingStrategy = getNamingStrategy();
if (namingStrategy != null) {
name = namingStrategy.getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}

5
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java

@ -40,10 +40,8 @@ import org.springframework.cglib.proxy.Enhancer; @@ -40,10 +40,8 @@ import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotatedMethod;
import org.springframework.objenesis.ObjenesisException;
@ -112,8 +110,6 @@ public class MvcUriComponentsBuilder { @@ -112,8 +110,6 @@ public class MvcUriComponentsBuilder {
private static final PathMatcher pathMatcher = new AntPathMatcher();
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private static final CompositeUriComponentsContributor defaultUriComponentsContributor;
static {
@ -608,7 +604,6 @@ public class MvcUriComponentsBuilder { @@ -608,7 +604,6 @@ public class MvcUriComponentsBuilder {
final Map<String, Object> uriVars = new HashMap<>();
for (int i = 0; i < paramCount; i++) {
MethodParameter param = annotatedMethod.getMethodParameters()[i];
param.initParameterNameDiscovery(parameterNameDiscoverer);
contributor.contributeMethodArgument(param, args[i], builder, uriVars);
}

2
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java

@ -187,7 +187,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter @@ -187,7 +187,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
private @Nullable ConfigurableBeanFactory beanFactory;

Loading…
Cancel
Save