Skip to content

Commit c813577

Browse files
committed
Consistently use DefaultParameterNameDiscoverer.getSharedInstance()
This includes MethodParameter resolving getParameterName() by default now. initParameterNameDiscovery(null) can be used to suppress such resolution. Closes gh-36024
1 parent ec6b773 commit c813577

File tree

19 files changed

+61
-41
lines changed

19 files changed

+61
-41
lines changed

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
import org.springframework.aop.ProxyMethodInvocation;
3131
import org.springframework.core.DefaultParameterNameDiscoverer;
32-
import org.springframework.core.ParameterNameDiscoverer;
3332
import org.springframework.util.Assert;
3433

3534
/**
@@ -51,8 +50,6 @@
5150
*/
5251
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {
5352

54-
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
55-
5653
private final ProxyMethodInvocation methodInvocation;
5754

5855
private @Nullable Object @Nullable [] args;
@@ -217,7 +214,7 @@ public Class<?>[] getParameterTypes() {
217214
public @Nullable String @Nullable [] getParameterNames() {
218215
@Nullable String[] parameterNames = this.parameterNames;
219216
if (parameterNames == null) {
220-
parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
217+
parameterNames = DefaultParameterNameDiscoverer.getSharedInstance().getParameterNames(getMethod());
221218
this.parameterNames = parameterNames;
222219
}
223220
return parameterNames;

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import org.springframework.core.DefaultParameterNameDiscoverer;
4646
import org.springframework.core.KotlinDetector;
4747
import org.springframework.core.MethodParameter;
48-
import org.springframework.core.ParameterNameDiscoverer;
4948
import org.springframework.core.ResolvableType;
5049
import org.springframework.util.Assert;
5150
import org.springframework.util.ClassUtils;
@@ -72,9 +71,6 @@
7271
*/
7372
public abstract class BeanUtils {
7473

75-
private static final ParameterNameDiscoverer parameterNameDiscoverer =
76-
new DefaultParameterNameDiscoverer();
77-
7874
private static final Set<Class<?>> unknownEditorTypes =
7975
Collections.newSetFromMap(new ConcurrentReferenceHashMap<>(64));
8076

@@ -659,7 +655,8 @@ public static MethodParameter getWriteMethodParameter(PropertyDescriptor pd) {
659655
@SuppressWarnings("NullAway") // Dataflow analysis limitation
660656
public static @Nullable String[] getParameterNames(Constructor<?> ctor) {
661657
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
662-
@Nullable String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
658+
@Nullable String[] paramNames = (cp != null ? cp.value() :
659+
DefaultParameterNameDiscoverer.getSharedInstance().getParameterNames(ctor));
663660
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
664661
int parameterCount = (KOTLIN_REFLECT_PRESENT && KotlinDelegate.hasDefaultConstructorMarker(ctor) ?
665662
ctor.getParameterCount() - 1 : ctor.getParameterCount());

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,24 @@ class CacheEvaluationContextFactory {
3939

4040
private @Nullable Supplier<ParameterNameDiscoverer> parameterNameDiscoverer;
4141

42+
4243
CacheEvaluationContextFactory(StandardEvaluationContext originalContext) {
4344
this.originalContext = originalContext;
4445
}
4546

47+
4648
public void setParameterNameDiscoverer(Supplier<ParameterNameDiscoverer> parameterNameDiscoverer) {
4749
this.parameterNameDiscoverer = parameterNameDiscoverer;
4850
}
4951

5052
public ParameterNameDiscoverer getParameterNameDiscoverer() {
5153
if (this.parameterNameDiscoverer == null) {
52-
this.parameterNameDiscoverer = SingletonSupplier.of(new DefaultParameterNameDiscoverer());
54+
this.parameterNameDiscoverer = SingletonSupplier.of(DefaultParameterNameDiscoverer.getSharedInstance());
5355
}
5456
return this.parameterNameDiscoverer.get();
5557
}
5658

59+
5760
/**
5861
* Creates a {@link CacheEvaluationContext} for the specified operation.
5962
* @param rootObject the {@code root} object to use for the context

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ public abstract class CachedExpressionEvaluator {
3838

3939
private final SpelExpressionParser parser;
4040

41-
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
42-
4341

4442
/**
4543
* Create a new instance with the default {@link SpelExpressionParser}.
@@ -69,7 +67,7 @@ protected SpelExpressionParser getParser() {
6967
* @since 4.3
7068
*/
7169
protected ParameterNameDiscoverer getParameterNameDiscoverer() {
72-
return this.parameterNameDiscoverer;
70+
return DefaultParameterNameDiscoverer.getSharedInstance();
7371
}
7472

7573
/**

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
183183

184184
private boolean exposeClassDescriptor = false;
185185

186-
private @Nullable ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
186+
private @Nullable ParameterNameDiscoverer parameterNameDiscoverer =
187+
DefaultParameterNameDiscoverer.getSharedInstance();
187188

188189

189190
/**
@@ -507,8 +508,8 @@ protected String getOperationDescription(Method method, String beanKey) {
507508
* @return the {@code MBeanParameterInfo} array
508509
*/
509510
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
510-
ParameterNameDiscoverer paramNameDiscoverer = getParameterNameDiscoverer();
511-
@Nullable String[] paramNames = (paramNameDiscoverer != null ? paramNameDiscoverer.getParameterNames(method) : null);
511+
ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
512+
@Nullable String[] paramNames = (pnd != null ? pnd.getParameterNames(method) : null);
512513
if (paramNames == null) {
513514
return new MBeanParameterInfo[0];
514515
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public class MethodValidationAdapter implements MethodValidator {
8787

8888
private MessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver();
8989

90-
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
90+
private ParameterNameDiscoverer parameterNameDiscoverer = DefaultParameterNameDiscoverer.getSharedInstance();
9191

9292
private ObjectNameResolver objectNameResolver = defaultObjectNameResolver;
9393

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.core;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
/**
2022
* Default implementation of the {@link ParameterNameDiscoverer} strategy interface,
2123
* delegating to the Java 8 standard reflection mechanism.
@@ -37,6 +39,8 @@ public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDisc
3739

3840
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
3941

42+
private static volatile @Nullable DefaultParameterNameDiscoverer sharedInstance;
43+
4044

4145
public DefaultParameterNameDiscoverer() {
4246
if (KOTLIN_REFLECT_PRESENT) {
@@ -47,4 +51,25 @@ public DefaultParameterNameDiscoverer() {
4751
addDiscoverer(new StandardReflectionParameterNameDiscoverer());
4852
}
4953

54+
55+
/**
56+
* Return a shared default {@code ParameterNameDiscoverer} instance,
57+
* lazily building it once needed.
58+
* @return the shared {@code ParameterNameDiscoverer} instance
59+
* @since 7.0.3
60+
*/
61+
public static ParameterNameDiscoverer getSharedInstance() {
62+
DefaultParameterNameDiscoverer pnd = sharedInstance;
63+
if (pnd == null) {
64+
synchronized (DefaultParameterNameDiscoverer.class) {
65+
pnd = sharedInstance;
66+
if (pnd == null) {
67+
pnd = new DefaultParameterNameDiscoverer();
68+
sharedInstance = pnd;
69+
}
70+
}
71+
}
72+
return pnd;
73+
}
74+
5075
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ public class MethodParameter {
8989

9090
private volatile Annotation @Nullable [] parameterAnnotations;
9191

92-
private volatile @Nullable ParameterNameDiscoverer parameterNameDiscoverer;
92+
private volatile @Nullable ParameterNameDiscoverer parameterNameDiscoverer =
93+
DefaultParameterNameDiscoverer.getSharedInstance();
9394

9495
volatile @Nullable String parameterName;
9596

@@ -667,6 +668,10 @@ public <A extends Annotation> boolean hasParameterAnnotation(Class<A> annotation
667668
* <p>This method does not actually try to retrieve the parameter name at
668669
* this point; it just allows discovery to happen when the application calls
669670
* {@link #getParameterName()} (if ever).
671+
* <p>Note: As of 7.0.3, a default parameter name discoverer is available.
672+
* This init method can be used to override the default discoverer or to
673+
* suppress discovery (passing {@code null}).
674+
* @see DefaultParameterNameDiscoverer#getSharedInstance()
670675
*/
671676
public void initParameterNameDiscovery(@Nullable ParameterNameDiscoverer parameterNameDiscoverer) {
672677
this.parameterNameDiscoverer = parameterNameDiscoverer;

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ void nestedWithTypeIndexReturnsNewInstance() throws Exception {
252252
assertThat(m3.getTypeIndexForCurrentLevel()).isEqualTo(3);
253253
}
254254

255+
@Test
256+
void parameterNames() {
257+
assertThat(stringParameter.getParameterName()).isEqualTo("str");
258+
assertThat(longParameter.getParameterName()).isEqualTo("lng");
259+
}
260+
255261
@Test
256262
void jspecifyNullableParameter() {
257263
assertThat(jspecifyNullableParameter.isOptional()).isTrue();
@@ -272,7 +278,8 @@ void springNonNullParameter() {
272278
assertThat(springNonNullParameter.isOptional()).isFalse();
273279
}
274280

275-
public int method(String p1, long p2) {
281+
282+
public int method(String str, long lng) {
276283
return 42;
277284
}
278285

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,18 @@ class MethodParameterKotlinTests {
117117
@Test
118118
fun `Parameter name for regular function`() {
119119
val methodParameter = returnMethodParameter("nullable", 0)
120-
methodParameter.initParameterNameDiscovery(KotlinReflectionParameterNameDiscoverer())
121120
assertThat(methodParameter.getParameterName()).isEqualTo("nullable")
122121
}
123122

124123
@Test
125124
fun `Parameter name for suspending function`() {
126125
val methodParameter = returnMethodParameter("suspendFun", 0)
127-
methodParameter.initParameterNameDiscovery(KotlinReflectionParameterNameDiscoverer())
128126
assertThat(methodParameter.getParameterName()).isEqualTo("p1")
129127
}
130128

131129
@Test
132130
fun `Continuation parameter name for suspending function`() {
133131
val methodParameter = returnMethodParameter("suspendFun", 1)
134-
methodParameter.initParameterNameDiscovery(KotlinReflectionParameterNameDiscoverer())
135132
assertThat(methodParameter.getParameterName()).isNull()
136133
}
137134

0 commit comments

Comments
 (0)