Skip to content

Commit 7f21443

Browse files
committed
Refine null-safety based on IDEA warnings
See gh-28797
1 parent 4189f8b commit 7f21443

File tree

22 files changed

+61
-47
lines changed

22 files changed

+61
-47
lines changed

spring-aop/src/main/java/org/springframework/aop/MethodMatcher.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.lang.reflect.Method;
2020

21+
import org.jspecify.annotations.Nullable;
22+
2123
/**
2224
* Part of a {@link Pointcut}: Checks whether the target method is eligible for advice.
2325
*
@@ -94,7 +96,7 @@ public interface MethodMatcher {
9496
* @return whether there's a runtime match
9597
* @see #matches(Method, Class)
9698
*/
97-
boolean matches(Method method, Class<?> targetClass, Object... args);
99+
boolean matches(Method method, Class<?> targetClass, @Nullable Object... args);
98100

99101

100102
/**

spring-aop/src/main/java/org/springframework/aop/TrueMethodMatcher.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.io.Serializable;
2020
import java.lang.reflect.Method;
2121

22+
import org.jspecify.annotations.Nullable;
23+
2224
/**
2325
* Canonical MethodMatcher instance that matches all methods.
2426
*
@@ -48,7 +50,7 @@ public boolean matches(Method method, Class<?> targetClass) {
4850
}
4951

5052
@Override
51-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
53+
public boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
5254
// Should never be invoked as isRuntime returns false.
5355
throw new UnsupportedOperationException();
5456
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ public boolean isRuntime() {
340340
}
341341

342342
@Override
343-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
343+
public boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
344344
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
345345

346346
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,

spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ public boolean matches(Method method, Class<?> targetClass) {
289289
}
290290

291291
@Override
292-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
292+
public boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
293293
// This can match only on declared pointcut.
294294
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass, args));
295295
}

spring-aop/src/main/java/org/springframework/aop/support/ControlFlowPointcut.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public boolean isRuntime() {
144144
}
145145

146146
@Override
147-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
147+
public boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
148148
incrementEvaluationCount();
149149

150150
for (StackTraceElement element : new Throwable().getStackTrace()) {

spring-aop/src/main/java/org/springframework/aop/support/MethodMatchers.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ public boolean isRuntime() {
151151
}
152152

153153
@Override
154-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
154+
public boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
155155
return this.mm1.matches(method, targetClass, args) || this.mm2.matches(method, targetClass, args);
156156
}
157157

@@ -303,7 +303,7 @@ public boolean isRuntime() {
303303
}
304304

305305
@Override
306-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
306+
public boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
307307
// Because a dynamic intersection may be composed of a static and dynamic part,
308308
// we must avoid calling the 3-arg matches method on a dynamic matcher, as
309309
// it will probably be an unsupported operation.
@@ -373,7 +373,7 @@ public boolean isRuntime() {
373373
}
374374

375375
@Override
376-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
376+
public boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
377377
return !this.original.matches(method, targetClass, args);
378378
}
379379

spring-aop/src/main/java/org/springframework/aop/support/StaticMethodMatcher.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.lang.reflect.Method;
2020

21+
import org.jspecify.annotations.Nullable;
22+
2123
import org.springframework.aop.MethodMatcher;
2224

2325
/**
@@ -34,7 +36,7 @@ public final boolean isRuntime() {
3436
}
3537

3638
@Override
37-
public final boolean matches(Method method, Class<?> targetClass, Object... args) {
39+
public final boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {
3840
// should never be invoked because isRuntime() returns false
3941
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
4042
}

spring-beans/src/main/java/org/springframework/beans/factory/ObjectProvider.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ default T getObject() throws BeansException {
7777
* @throws BeansException in case of creation errors
7878
* @see #getObject()
7979
*/
80-
default T getObject(Object... args) throws BeansException {
80+
default T getObject(@Nullable Object... args) throws BeansException {
8181
throw new UnsupportedOperationException("Retrieval with arguments not supported -" +
8282
"for custom ObjectProvider classes, implement getObject(Object...) for your purposes");
8383
}

spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
140140

141141
Constructor<?> constructorToUse = null;
142142
ArgumentsHolder argsHolderToUse = null;
143-
Object[] argsToUse = null;
143+
@Nullable Object[] argsToUse = null;
144144

145145
if (explicitArgs != null) {
146146
argsToUse = explicitArgs;
@@ -227,7 +227,7 @@ public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
227227
Class<?>[] paramTypes = candidate.getParameterTypes();
228228
if (resolvedValues != null) {
229229
try {
230-
String[] paramNames = null;
230+
@Nullable String[] paramNames = null;
231231
if (resolvedValues.containsNamedArgument()) {
232232
paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
233233
if (paramNames == null) {
@@ -437,7 +437,7 @@ public BeanWrapper instantiateUsingFactoryMethod(
437437
argsToUse = explicitArgs;
438438
}
439439
else {
440-
Object[] argsToResolve = null;
440+
@Nullable Object[] argsToResolve = null;
441441
synchronized (mbd.constructorArgumentLock) {
442442
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
443443
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
@@ -536,7 +536,7 @@ public BeanWrapper instantiateUsingFactoryMethod(
536536
else {
537537
// Resolved constructor arguments: type conversion and/or autowiring necessary.
538538
try {
539-
String[] paramNames = null;
539+
@Nullable String[] paramNames = null;
540540
if (resolvedValues != null && resolvedValues.containsNamedArgument()) {
541541
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
542542
if (pnd != null) {
@@ -719,7 +719,7 @@ private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd,
719719
*/
720720
private ArgumentsHolder createArgumentArray(
721721
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
722-
BeanWrapper bw, Class<?>[] paramTypes, String @Nullable [] paramNames, Executable executable,
722+
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String @Nullable [] paramNames, Executable executable,
723723
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
724724

725725
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ public T getObject() throws BeansException {
422422
return resolved;
423423
}
424424
@Override
425-
public T getObject(Object... args) throws BeansException {
425+
public T getObject(@Nullable Object... args) throws BeansException {
426426
T resolved = resolveBean(requiredType, args, false);
427427
if (resolved == null) {
428428
throw new NoSuchBeanDefinitionException(requiredType);
@@ -2147,7 +2147,7 @@ private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor desc
21472147
* Create an {@link Optional} wrapper for the specified dependency.
21482148
*/
21492149
private Optional<?> createOptionalDependency(
2150-
DependencyDescriptor descriptor, @Nullable String beanName, final Object... args) {
2150+
DependencyDescriptor descriptor, @Nullable String beanName, final @Nullable Object... args) {
21512151

21522152
DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
21532153
@Override
@@ -2317,7 +2317,7 @@ public Object getObject() throws BeansException {
23172317
}
23182318

23192319
@Override
2320-
public Object getObject(final Object... args) throws BeansException {
2320+
public Object getObject(final @Nullable Object... args) throws BeansException {
23212321
if (this.optional) {
23222322
return createOptionalDependency(this.descriptor, this.beanName, args);
23232323
}

spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ else if (beanNames.length > 1) {
301301
}
302302
}
303303
@Override
304-
public T getObject(Object... args) throws BeansException {
304+
public T getObject(@Nullable Object... args) throws BeansException {
305305
String[] beanNames = getBeanNamesForType(requiredType);
306306
if (beanNames.length == 1) {
307307
return (T) getBean(beanNames[0], args);

spring-context/src/main/java/org/springframework/context/annotation/BeanMethod.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void validate(ProblemReporter problemReporter) {
6363
return;
6464
}
6565

66-
Map<String, Object> attributes =
66+
Map<String, @Nullable Object> attributes =
6767
getConfigurationClass().getMetadata().getAnnotationAttributes(Configuration.class.getName());
6868
if (attributes != null && (Boolean) attributes.get("proxyBeanMethods") && !getMetadata().isOverridable()) {
6969
// instance @Bean methods within @Configuration classes must be overridable to accommodate CGLIB

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> getImportBeanDefinitionRe
220220

221221
@SuppressWarnings("NullAway") // Reflection
222222
void validate(ProblemReporter problemReporter) {
223-
Map<String, Object> attributes = this.metadata.getAnnotationAttributes(Configuration.class.getName());
223+
Map<String, @Nullable Object> attributes = this.metadata.getAnnotationAttributes(Configuration.class.getName());
224224

225225
// A configuration class may not be final (CGLIB limitation) unless it declares proxyBeanMethods=false
226226
if (attributes != null && (Boolean) attributes.get("proxyBeanMethods") && this.metadata.isFinal()) {

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.apache.commons.logging.Log;
2828
import org.apache.commons.logging.LogFactory;
29+
import org.jspecify.annotations.Nullable;
2930

3031
import org.springframework.beans.factory.BeanDefinitionStoreException;
3132
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
@@ -309,7 +310,7 @@ protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String
309310
ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());
310311
return true;
311312
}
312-
Map<String, Object> attributes =
313+
Map<String, @Nullable Object> attributes =
313314
configClass.getMetadata().getAnnotationAttributes(Configuration.class.getName());
314315
if ((attributes != null && (Boolean) attributes.get("enforceUniqueMethods")) ||
315316
!this.registry.isBeanDefinitionOverridable(beanName)) {

spring-context/src/main/java/org/springframework/context/annotation/ProfileCondition.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.context.annotation;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
import org.springframework.core.type.AnnotatedTypeMetadata;
2022
import org.springframework.util.MultiValueMap;
2123

@@ -33,7 +35,7 @@ class ProfileCondition implements Condition {
3335
@Override
3436
@SuppressWarnings("NullAway") // Reflection
3537
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
36-
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
38+
MultiValueMap<String, @Nullable Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
3739
if (attrs != null) {
3840
for (Object value : attrs.get("value")) {
3941
if (context.getEnvironment().matchesProfiles((String[]) value)) {

spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public void setBeanFactory(BeanFactory beanFactory) {
139139
}
140140

141141
@Override
142-
public org.springframework.jmx.export.metadata.ManagedOperationParameter[] getManagedOperationParameters(Method method)
142+
public org.springframework.jmx.export.metadata.@Nullable ManagedOperationParameter[] getManagedOperationParameters(Method method)
143143
throws InvalidMetadataException {
144144

145145
List<MergedAnnotation<? extends Annotation>> anns = getRepeatableAnnotations(
@@ -149,7 +149,7 @@ public org.springframework.jmx.export.metadata.ManagedOperationParameter[] getMa
149149
}
150150

151151
@Override
152-
public org.springframework.jmx.export.metadata.ManagedNotification[] getManagedNotifications(Class<?> clazz)
152+
public org.springframework.jmx.export.metadata.@Nullable ManagedNotification[] getManagedNotifications(Class<?> clazz)
153153
throws InvalidMetadataException {
154154

155155
List<MergedAnnotation<? extends Annotation>> anns = getRepeatableAnnotations(

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.beans.PropertyDescriptor;
2020
import java.lang.reflect.Method;
21+
import java.util.Objects;
2122

2223
import javax.management.Descriptor;
2324
import javax.management.MBeanParameterInfo;
@@ -259,15 +260,15 @@ protected String getOperationDescription(Method method, String beanKey) {
259260
*/
260261
@Override
261262
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
262-
ManagedOperationParameter[] params = obtainAttributeSource().getManagedOperationParameters(method);
263+
@Nullable ManagedOperationParameter[] params = obtainAttributeSource().getManagedOperationParameters(method);
263264
if (ObjectUtils.isEmpty(params)) {
264265
return super.getOperationParameters(method, beanKey);
265266
}
266267

267268
MBeanParameterInfo[] parameterInfo = new MBeanParameterInfo[params.length];
268269
Class<?>[] methodParameters = method.getParameterTypes();
269270
for (int i = 0; i < params.length; i++) {
270-
ManagedOperationParameter param = params[i];
271+
ManagedOperationParameter param = Objects.requireNonNull(params[i]);
271272
parameterInfo[i] =
272273
new MBeanParameterInfo(param.getName(), methodParameters[i].getName(), param.getDescription());
273274
}
@@ -280,14 +281,14 @@ protected MBeanParameterInfo[] getOperationParameters(Method method, String bean
280281
*/
281282
@Override
282283
protected ModelMBeanNotificationInfo[] getNotificationInfo(Object managedBean, String beanKey) {
283-
ManagedNotification[] notificationAttributes =
284+
@Nullable ManagedNotification[] notificationAttributes =
284285
obtainAttributeSource().getManagedNotifications(getClassToExpose(managedBean));
285286
ModelMBeanNotificationInfo[] notificationInfos =
286287
new ModelMBeanNotificationInfo[notificationAttributes.length];
287288

288289
for (int i = 0; i < notificationAttributes.length; i++) {
289290
ManagedNotification attribute = notificationAttributes[i];
290-
notificationInfos[i] = JmxMetadataUtils.convertToModelMBeanNotificationInfo(attribute);
291+
notificationInfos[i] = JmxMetadataUtils.convertToModelMBeanNotificationInfo(Objects.requireNonNull(attribute));
291292
}
292293

293294
return notificationInfos;

spring-context/src/main/java/org/springframework/jmx/export/metadata/JmxAttributeSource.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public interface JmxAttributeSource {
8080
* @return the parameter information.
8181
* @throws InvalidMetadataException in the case of invalid attributes.
8282
*/
83-
ManagedOperationParameter[] getManagedOperationParameters(Method method) throws InvalidMetadataException;
83+
@Nullable ManagedOperationParameter[] getManagedOperationParameters(Method method) throws InvalidMetadataException;
8484

8585
/**
8686
* Implementations should return an array of {@link ManagedNotification ManagedNotifications}
@@ -90,7 +90,7 @@ public interface JmxAttributeSource {
9090
* @return the notification information
9191
* @throws InvalidMetadataException in the case of invalid metadata
9292
*/
93-
ManagedNotification[] getManagedNotifications(Class<?> clazz) throws InvalidMetadataException;
93+
@Nullable ManagedNotification[] getManagedNotifications(Class<?> clazz) throws InvalidMetadataException;
9494

9595

9696

spring-context/src/main/java/org/springframework/jndi/support/SimpleJndiBeanFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public T getObject() throws BeansException {
162162
return getBean(requiredType);
163163
}
164164
@Override
165-
public T getObject(Object... args) throws BeansException {
165+
public T getObject(@Nullable Object... args) throws BeansException {
166166
return getBean(requiredType, args);
167167
}
168168
@Override

spring-expression/src/main/java/org/springframework/expression/ConstructorExecutor.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.expression;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
/**
2022
* A {@code ConstructorExecutor} is built by a {@link ConstructorResolver} and
2123
* can be cached by the infrastructure to repeat an operation quickly without
@@ -49,6 +51,6 @@ public interface ConstructorExecutor {
4951
* @throws AccessException if there is a problem executing the constructor or
5052
* if this {@code ConstructorExecutor} has become stale
5153
*/
52-
TypedValue execute(EvaluationContext context, Object... arguments) throws AccessException;
54+
TypedValue execute(EvaluationContext context, @Nullable Object... arguments) throws AccessException;
5355

5456
}

spring-expression/src/main/java/org/springframework/expression/MethodExecutor.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.expression;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
/**
2022
* A {@code MethodExecutor} is built by a {@link MethodResolver} and can be cached
2123
* by the infrastructure to repeat an operation quickly without going back to the
@@ -50,6 +52,6 @@ public interface MethodExecutor {
5052
* @throws AccessException if there is a problem executing the method or
5153
* if this {@code MethodExecutor} has become stale
5254
*/
53-
TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException;
55+
TypedValue execute(EvaluationContext context, Object target, @Nullable Object... arguments) throws AccessException;
5456

5557
}

0 commit comments

Comments
 (0)