mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Consistently use DefaultParameterNameDiscoverer.getSharedInstance()
This includes MethodParameter resolving getParameterName() by default now. initParameterNameDiscovery(null) can be used to suppress such resolution. Closes gh-36024
This commit is contained in:
+1
-4
@@ -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;
|
||||
*/
|
||||
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,
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
*/
|
||||
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 {
|
||||
@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());
|
||||
|
||||
+4
-1
@@ -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
|
||||
|
||||
+1
-3
@@ -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 {
|
||||
* @since 4.3
|
||||
*/
|
||||
protected ParameterNameDiscoverer getParameterNameDiscoverer() {
|
||||
return this.parameterNameDiscoverer;
|
||||
return DefaultParameterNameDiscoverer.getSharedInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-3
@@ -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
|
||||
* @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];
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
@@ -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
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
* <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;
|
||||
|
||||
@@ -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 {
|
||||
assertThat(springNonNullParameter.isOptional()).isFalse();
|
||||
}
|
||||
|
||||
public int method(String p1, long p2) {
|
||||
|
||||
public int method(String str, long lng) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
|
||||
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
|
||||
|
||||
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -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
@@ -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 {
|
||||
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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
@@ -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 {
|
||||
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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
|
||||
+4
-3
@@ -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
@@ -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 {
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user