Skip to content

Commit f52f833

Browse files
committed
Specify generic type nullness in spring-aop
See spring-projectsgh-34140
1 parent c0039fb commit f52f833

12 files changed

+41
-33
lines changed

Diff for: spring-aop/src/main/java/org/springframework/aop/AfterReturningAdvice.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -41,6 +41,6 @@ public interface AfterReturningAdvice extends AfterAdvice {
4141
* allowed by the method signature. Otherwise the exception
4242
* will be wrapped as a runtime exception.
4343
*/
44-
void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
44+
void afterReturning(@Nullable Object returnValue, Method method, @Nullable Object[] args, @Nullable Object target) throws Throwable;
4545

4646
}

Diff for: spring-aop/src/main/java/org/springframework/aop/MethodBeforeAdvice.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,6 +40,6 @@ public interface MethodBeforeAdvice extends BeforeAdvice {
4040
* allowed by the method signature. Otherwise the exception
4141
* will be wrapped as a runtime exception.
4242
*/
43-
void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
43+
void before(Method method, @Nullable Object[] args, @Nullable Object target) throws Throwable;
4444

4545
}

Diff for: spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
4343
import org.springframework.aop.support.StaticMethodMatcher;
4444
import org.springframework.core.DefaultParameterNameDiscoverer;
4545
import org.springframework.core.ParameterNameDiscoverer;
46+
import org.springframework.lang.Contract;
4647
import org.springframework.util.Assert;
4748
import org.springframework.util.ClassUtils;
4849
import org.springframework.util.CollectionUtils;
@@ -258,10 +259,11 @@ public void setArgumentNames(String argumentNames) {
258259
* or in an advice annotation.
259260
* @param argumentNames list of argument names
260261
*/
261-
public void setArgumentNamesFromStringArray(String... argumentNames) {
262+
public void setArgumentNamesFromStringArray(@Nullable String... argumentNames) {
262263
this.argumentNames = new String[argumentNames.length];
263264
for (int i = 0; i < argumentNames.length; i++) {
264-
this.argumentNames[i] = argumentNames[i].strip();
265+
String argumentName = argumentNames[i];
266+
this.argumentNames[i] = argumentName != null ? argumentName.strip() : null;
265267
if (!isVariableName(this.argumentNames[i])) {
266268
throw new IllegalArgumentException(
267269
"'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
@@ -274,7 +276,7 @@ public void setArgumentNamesFromStringArray(String... argumentNames) {
274276
if (firstArgType == JoinPoint.class ||
275277
firstArgType == ProceedingJoinPoint.class ||
276278
firstArgType == JoinPoint.StaticPart.class) {
277-
String[] oldNames = this.argumentNames;
279+
@Nullable String[] oldNames = this.argumentNames;
278280
this.argumentNames = new String[oldNames.length + 1];
279281
this.argumentNames[0] = "THIS_JOIN_POINT";
280282
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
@@ -346,7 +348,8 @@ protected Class<?> getDiscoveredThrowingType() {
346348
return this.discoveredThrowingType;
347349
}
348350

349-
private static boolean isVariableName(String name) {
351+
@Contract("null -> false")
352+
private static boolean isVariableName(@Nullable String name) {
350353
return AspectJProxyUtils.isVariableName(name);
351354
}
352355

@@ -456,6 +459,7 @@ protected ParameterNameDiscoverer createParameterNameDiscoverer() {
456459
return discoverer;
457460
}
458461

462+
@SuppressWarnings("NullAway") // Dataflow analysis limitation
459463
private void bindExplicitArguments(int numArgumentsLeftToBind) {
460464
Assert.state(this.argumentNames != null, "No argument names available");
461465
this.argumentBindings = new HashMap<>();
@@ -623,8 +627,8 @@ protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMat
623627
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
624628
}
625629

626-
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
627-
Object[] actualArgs = args;
630+
protected Object invokeAdviceMethodWithGivenArgs(@Nullable Object[] args) throws Throwable {
631+
@Nullable Object[] actualArgs = args;
628632
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
629633
actualArgs = null;
630634
}

Diff for: spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterReturningAdvice.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ public void setReturningName(String name) {
6262
}
6363

6464
@Override
65-
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
65+
public void afterReturning(@Nullable Object returnValue, Method method, @Nullable Object[] args, @Nullable Object target) throws Throwable {
6666
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
6767
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
6868
}

Diff for: spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJMethodBeforeAdvice.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ public AspectJMethodBeforeAdvice(
4141

4242

4343
@Override
44-
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
44+
public void before(Method method, @Nullable Object[] args, @Nullable Object target) throws Throwable {
4545
invokeAdviceMethod(getJoinPointMatch(), null, null);
4646
}
4747

Diff for: spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJProxyUtils.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
import org.springframework.aop.Advisor;
2424
import org.springframework.aop.PointcutAdvisor;
2525
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
26+
import org.springframework.lang.Contract;
2627
import org.springframework.util.StringUtils;
2728

2829
/**
@@ -76,6 +77,7 @@ private static boolean isAspectJAdvice(Advisor advisor) {
7677
pointcutAdvisor.getPointcut() instanceof AspectJExpressionPointcut));
7778
}
7879

80+
@Contract("null -> false")
7981
static boolean isVariableName(@Nullable String name) {
8082
if (!StringUtils.hasLength(name)) {
8183
return false;

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

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
5555

5656
private final ProxyMethodInvocation methodInvocation;
5757

58-
private Object @Nullable [] args;
58+
private @Nullable Object @Nullable [] args;
5959

6060
/** Lazily initialized signature object. */
6161
private @Nullable Signature signature;
@@ -114,7 +114,8 @@ public Object getThis() {
114114
}
115115

116116
@Override
117-
public Object[] getArgs() {
117+
@SuppressWarnings("NullAway") // Overridden method does not define nullness
118+
public @Nullable Object[] getArgs() {
118119
if (this.args == null) {
119120
this.args = this.methodInvocation.getArguments().clone();
120121
}
@@ -174,7 +175,7 @@ public String toString() {
174175
*/
175176
private class MethodSignatureImpl implements MethodSignature {
176177

177-
private volatile String @Nullable [] parameterNames;
178+
private volatile @Nullable String @Nullable [] parameterNames;
178179

179180
@Override
180181
public String getName() {
@@ -212,8 +213,9 @@ public Class<?>[] getParameterTypes() {
212213
}
213214

214215
@Override
215-
public String @Nullable [] getParameterNames() {
216-
String[] parameterNames = this.parameterNames;
216+
@SuppressWarnings("NullAway") // Overridden method does not define nullness
217+
public @Nullable String @Nullable [] getParameterNames() {
218+
@Nullable String[] parameterNames = this.parameterNames;
217219
if (parameterNames == null) {
218220
parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
219221
this.parameterNames = parameterNames;

Diff for: spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -302,7 +302,7 @@ private List<Method> getAdvisorMethods(Class<?> aspectClass) {
302302
// Now to configure the advice...
303303
springAdvice.setAspectName(aspectName);
304304
springAdvice.setDeclarationOrder(declarationOrder);
305-
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
305+
@Nullable String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
306306
if (argNames != null) {
307307
springAdvice.setArgumentNamesFromStringArray(argNames);
308308
}

Diff for: spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -704,7 +704,7 @@ public DynamicAdvisedInterceptor(AdvisedSupport advised) {
704704
// Note that the final invoker must be an InvokerInterceptor, so we know
705705
// it does nothing but a reflective operation on the target, and no hot
706706
// swapping or fancy proxying.
707-
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
707+
@Nullable Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
708708
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
709709
}
710710
else {

Diff for: spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -211,7 +211,7 @@ else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
211211
// We can skip creating a MethodInvocation: just invoke the target directly
212212
// Note that the final invoker must be an InvokerInterceptor so we know it does
213213
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
214-
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
214+
@Nullable Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
215215
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
216216
}
217217
else {

Diff for: spring-aop/src/main/java/org/springframework/aop/framework/ReflectiveMethodInvocation.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -201,7 +201,7 @@ public void setArguments(@Nullable Object... arguments) {
201201
*/
202202
@Override
203203
public MethodInvocation invocableClone() {
204-
Object[] cloneArguments = this.arguments;
204+
@Nullable Object[] cloneArguments = this.arguments;
205205
if (this.arguments.length > 0) {
206206
// Build an independent copy of the arguments array.
207207
cloneArguments = this.arguments.clone();

Diff for: spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -116,8 +116,8 @@ public AsyncExecutionAspectSupport(@Nullable Executor defaultExecutor, AsyncUnca
116116
* applying the corresponding default if a supplier is not resolvable.
117117
* @since 5.1
118118
*/
119-
public void configure(@Nullable Supplier<Executor> defaultExecutor,
120-
@Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
119+
public void configure(@Nullable Supplier<? extends @Nullable Executor> defaultExecutor,
120+
@Nullable Supplier<? extends @Nullable AsyncUncaughtExceptionHandler> exceptionHandler) {
121121

122122
this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory));
123123
this.exceptionHandler = new SingletonSupplier<>(exceptionHandler, SimpleAsyncUncaughtExceptionHandler::new);

0 commit comments

Comments
 (0)