Switch to JSpecify annotations

This commit updates the whole Spring Framework codebase to use JSpecify
annotations instead of Spring null-safety annotations with JSR 305
semantics.

JSpecify provides signficant enhancements such as properly defined
specifications, a canonical dependency with no split-package issue,
better tooling, better Kotlin integration and the capability to specify
generic type, array and varargs element null-safety. Generic type
null-safety is not defined by this commit yet and will be specified
later.

A key difference is that Spring null-safety annotations, following
JSR 305 semantics, apply to fields, parameters and return values,
while JSpecify annotations apply to type usages. That's why this
commit moves nullability annotations closer to the type for fields
and return values.

See gh-28797
This commit is contained in:
Sébastien Deleuze
2024-12-03 15:22:37 +01:00
parent fcb8aed03f
commit bc5d771a06
3459 changed files with 14118 additions and 22059 deletions

View File

@@ -20,8 +20,9 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.jspecify.annotations.Nullable;
import org.springframework.javapoet.ClassName;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

View File

@@ -21,11 +21,12 @@ import java.util.List;
import javax.lang.model.element.Modifier;
import org.jspecify.annotations.Nullable;
import org.springframework.javapoet.ClassName;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.MethodSpec;
import org.springframework.javapoet.TypeName;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -39,8 +40,7 @@ public class DefaultMethodReference implements MethodReference {
private final MethodSpec method;
@Nullable
private final ClassName declaringClass;
private final @Nullable ClassName declaringClass;
public DefaultMethodReference(MethodSpec method, @Nullable ClassName declaringClass) {

View File

@@ -21,10 +21,11 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.javapoet.ClassName;
import org.springframework.javapoet.JavaFile;
import org.springframework.javapoet.TypeSpec;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -37,8 +38,7 @@ import org.springframework.util.Assert;
*/
public final class GeneratedClass {
@Nullable
private final GeneratedClass enclosingClass;
private final @Nullable GeneratedClass enclosingClass;
private final ClassName name;
@@ -98,8 +98,7 @@ public final class GeneratedClass {
* instance represents a top-level class.
* @return the enclosing generated class, if any
*/
@Nullable
public GeneratedClass getEnclosingClass() {
public @Nullable GeneratedClass getEnclosingClass() {
return this.enclosingClass;
}

View File

@@ -23,9 +23,10 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.javapoet.ClassName;
import org.springframework.javapoet.TypeSpec;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -18,9 +18,10 @@ package org.springframework.aot.generate;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.InputStreamSource;
import org.springframework.javapoet.JavaFile;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -264,8 +265,7 @@ public interface GeneratedFiles {
* Return an {@link InputStreamSource} for the content of the file or
* {@code null} if the file does not exist.
*/
@Nullable
public InputStreamSource getContent() {
public @Nullable InputStreamSource getContent() {
return (exists() ? this.existingContent.get() : null);
}

View File

@@ -16,10 +16,11 @@
package org.springframework.aot.generate;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.AbstractTypeReference;
import org.springframework.aot.hint.TypeReference;
import org.springframework.javapoet.ClassName;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -37,8 +38,7 @@ public final class GeneratedTypeReference extends AbstractTypeReference {
this.className = className;
}
@Nullable
private static GeneratedTypeReference safeCreate(@Nullable ClassName className) {
private static @Nullable GeneratedTypeReference safeCreate(@Nullable ClassName className) {
return (className != null ? new GeneratedTypeReference(className) : null);
}

View File

@@ -23,8 +23,9 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.InputStreamSource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.function.ThrowingConsumer;
@@ -64,8 +65,7 @@ public class InMemoryGeneratedFiles implements GeneratedFiles {
* @return the file content or {@code null} if no file could be found
* @throws IOException on read error
*/
@Nullable
public String getGeneratedFileContent(Kind kind, String path) throws IOException {
public @Nullable String getGeneratedFileContent(Kind kind, String path) throws IOException {
InputStreamSource source = getGeneratedFile(kind, path);
if (source != null) {
return new String(source.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
@@ -79,8 +79,7 @@ public class InMemoryGeneratedFiles implements GeneratedFiles {
* @param path the path of the file
* @return the file source or {@code null} if no file could be found
*/
@Nullable
public InputStreamSource getGeneratedFile(Kind kind, String path) {
public @Nullable InputStreamSource getGeneratedFile(Kind kind, String path) {
Assert.notNull(kind, "'kind' must not be null");
Assert.hasLength(path, "'path' must not be empty");
Map<String, InputStreamSource> paths = this.files.get(kind);

View File

@@ -19,7 +19,8 @@ package org.springframework.aot.generate;
import java.util.Arrays;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

View File

@@ -18,10 +18,11 @@ package org.springframework.aot.generate;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.javapoet.ClassName;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.TypeName;
import org.springframework.lang.Nullable;
/**
* A reference to a method with convenient code generation for
@@ -74,8 +75,7 @@ public interface MethodReference {
* @param argumentType the argument type
* @return the code for this argument, or {@code null}
*/
@Nullable
CodeBlock generateCode(TypeName argumentType);
@Nullable CodeBlock generateCode(TypeName argumentType);
/**
* Factory method that returns an {@link ArgumentCodeGenerator} that

View File

@@ -16,7 +16,7 @@
package org.springframework.aot.generate;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Thrown when value code generation fails.
@@ -27,8 +27,7 @@ import org.springframework.lang.Nullable;
@SuppressWarnings("serial")
public class ValueCodeGenerationException extends RuntimeException {
@Nullable
private final Object value;
private final @Nullable Object value;
protected ValueCodeGenerationException(String message, @Nullable Object value, @Nullable Throwable cause) {
@@ -54,8 +53,7 @@ public class ValueCodeGenerationException extends RuntimeException {
/**
* Return the value that failed to be generated.
*/
@Nullable
public Object getValue() {
public @Nullable Object getValue() {
return this.value;
}

View File

@@ -20,8 +20,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.javapoet.CodeBlock;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -41,8 +42,7 @@ public final class ValueCodeGenerator {
private final List<Delegate> delegates;
@Nullable
private final GeneratedMethods generatedMethods;
private final @Nullable GeneratedMethods generatedMethods;
private ValueCodeGenerator(List<Delegate> delegates, @Nullable GeneratedMethods generatedMethods) {
@@ -128,8 +128,7 @@ public final class ValueCodeGenerator {
* {@code null} if no specific scope is set.
* @return the generated methods to use for code generation
*/
@Nullable
public GeneratedMethods getGeneratedMethods() {
public @Nullable GeneratedMethods getGeneratedMethods() {
return this.generatedMethods;
}
@@ -149,8 +148,7 @@ public final class ValueCodeGenerator {
* @return the code that represents the specified value or {@code null} if
* the specified value is not supported.
*/
@Nullable
CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value);
@Nullable CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value);
}
}

View File

@@ -30,11 +30,12 @@ import java.util.TreeMap;
import java.util.TreeSet;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.generate.ValueCodeGenerator.Delegate;
import org.springframework.core.ResolvableType;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.CodeBlock.Builder;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -94,8 +95,7 @@ public abstract class ValueCodeGeneratorDelegates {
@Override
@SuppressWarnings("unchecked")
@Nullable
public CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value) {
if (this.collectionType.isInstance(value)) {
T collection = (T) value;
if (collection.isEmpty()) {
@@ -136,8 +136,7 @@ public abstract class ValueCodeGeneratorDelegates {
private static final CodeBlock EMPTY_RESULT = CodeBlock.of("$T.emptyMap()", Collections.class);
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value) {
if (value instanceof Map<?, ?> map) {
if (map.isEmpty()) {
return EMPTY_RESULT;
@@ -154,8 +153,7 @@ public abstract class ValueCodeGeneratorDelegates {
* @return the code that represents the specified map or {@code null} if
* the specified map is not supported.
*/
@Nullable
protected CodeBlock generateMapCode(ValueCodeGenerator valueCodeGenerator, Map<?, ?> map) {
protected @Nullable CodeBlock generateMapCode(ValueCodeGenerator valueCodeGenerator, Map<?, ?> map) {
map = orderForCodeConsistency(map);
boolean useOfEntries = map.size() > 10;
CodeBlock.Builder code = CodeBlock.builder();
@@ -209,8 +207,7 @@ public abstract class ValueCodeGeneratorDelegates {
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
if (value instanceof Boolean || value instanceof Integer) {
return CodeBlock.of("$L", value);
}
@@ -252,8 +249,7 @@ public abstract class ValueCodeGeneratorDelegates {
private static class StringDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
if (value instanceof String) {
return CodeBlock.of("$S", value);
}
@@ -268,8 +264,7 @@ public abstract class ValueCodeGeneratorDelegates {
private static class CharsetDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
if (value instanceof Charset charset) {
return CodeBlock.of("$T.forName($S)", Charset.class, charset.name());
}
@@ -284,8 +279,7 @@ public abstract class ValueCodeGeneratorDelegates {
private static class EnumDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
if (value instanceof Enum<?> enumValue) {
return CodeBlock.of("$T.$L", enumValue.getDeclaringClass(),
enumValue.name());
@@ -301,8 +295,7 @@ public abstract class ValueCodeGeneratorDelegates {
private static class ClassDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
if (value instanceof Class<?> clazz) {
return CodeBlock.of("$T.class", ClassUtils.getUserClass(clazz));
}
@@ -317,8 +310,7 @@ public abstract class ValueCodeGeneratorDelegates {
private static class ResolvableTypeDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
if (value instanceof ResolvableType resolvableType) {
return generateCode(resolvableType, false);
}
@@ -360,8 +352,7 @@ public abstract class ValueCodeGeneratorDelegates {
private static class ArrayDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
public @Nullable CodeBlock generateCode(ValueCodeGenerator codeGenerator, Object value) {
if (value.getClass().isArray()) {
Stream<CodeBlock> elements = Arrays.stream(ObjectUtils.toObjectArray(value))
.map(codeGenerator::generateCode);

View File

@@ -2,9 +2,7 @@
* Support classes for components that contribute generated code equivalent to a
* runtime behavior.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.generate;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -18,7 +18,7 @@ package org.springframework.aot.hint;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Base {@link TypeReference} implementation that ensures consistent behaviour
@@ -34,8 +34,7 @@ public abstract class AbstractTypeReference implements TypeReference {
private final String simpleName;
@Nullable
private final TypeReference enclosingType;
private final @Nullable TypeReference enclosingType;
protected AbstractTypeReference(String packageName, String simpleName, @Nullable TypeReference enclosingType) {
@@ -63,9 +62,8 @@ public abstract class AbstractTypeReference implements TypeReference {
return this.simpleName;
}
@Nullable
@Override
public TypeReference getEnclosingType() {
public @Nullable TypeReference getEnclosingType() {
return this.enclosingType;
}

View File

@@ -29,13 +29,13 @@ import java.util.function.Consumer;
import kotlin.jvm.JvmClassMappingKt;
import kotlin.reflect.KClass;
import org.jspecify.annotations.Nullable;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

View File

@@ -16,7 +16,8 @@
package org.springframework.aot.hint;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -33,8 +34,7 @@ public interface ConditionalHint {
* {@code null} if this hint should always been applied.
* @return the reachable type, if any
*/
@Nullable
TypeReference getReachableType();
@Nullable TypeReference getReachableType();
/**
* Whether the condition described for this hint is met. If it is not,

View File

@@ -24,7 +24,8 @@ import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -113,8 +114,7 @@ public final class ExecutableHint extends MemberHint implements Comparable<Execu
private final List<TypeReference> parameterTypes;
@Nullable
private ExecutableMode mode;
private @Nullable ExecutableMode mode;
Builder(String name, List<TypeReference> parameterTypes) {

View File

@@ -18,7 +18,7 @@ package org.springframework.aot.hint;
import java.lang.reflect.Executable;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Represent the need of reflection for a given {@link Executable}.

View File

@@ -20,7 +20,7 @@ package org.springframework.aot.hint;
import java.io.Serializable;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A hint that describes the need for Java serialization at runtime.
@@ -32,8 +32,7 @@ public final class JavaSerializationHint implements ConditionalHint {
private final TypeReference type;
@Nullable
private final TypeReference reachableType;
private final @Nullable TypeReference reachableType;
JavaSerializationHint(Builder builder) {
@@ -51,8 +50,7 @@ public final class JavaSerializationHint implements ConditionalHint {
}
@Override
@Nullable
public TypeReference getReachableType() {
public @Nullable TypeReference getReachableType() {
return this.reachableType;
}
@@ -75,8 +73,7 @@ public final class JavaSerializationHint implements ConditionalHint {
private final TypeReference type;
@Nullable
private TypeReference reachableType;
private @Nullable TypeReference reachableType;
Builder(TypeReference type) {
this.type = type;

View File

@@ -22,7 +22,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A hint that describes the need for a JDK interface-based {@link Proxy}.
@@ -35,8 +35,7 @@ public final class JdkProxyHint implements ConditionalHint {
private final List<TypeReference> proxiedInterfaces;
@Nullable
private final TypeReference reachableType;
private final @Nullable TypeReference reachableType;
private JdkProxyHint(Builder builder) {
@@ -71,9 +70,8 @@ public final class JdkProxyHint implements ConditionalHint {
return this.proxiedInterfaces;
}
@Nullable
@Override
public TypeReference getReachableType() {
public @Nullable TypeReference getReachableType() {
return this.reachableType;
}
@@ -97,8 +95,7 @@ public final class JdkProxyHint implements ConditionalHint {
private final LinkedList<TypeReference> proxiedInterfaces;
@Nullable
private TypeReference reachableType;
private @Nullable TypeReference reachableType;
Builder() {
this.proxiedInterfaces = new LinkedList<>();

View File

@@ -26,8 +26,9 @@ import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.TypeHint.Builder;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -59,8 +60,7 @@ public class ReflectionHints {
* @param type the type to inspect
* @return the reflection hints for this type, or {@code null}
*/
@Nullable
public TypeHint getTypeHint(TypeReference type) {
public @Nullable TypeHint getTypeHint(TypeReference type) {
Builder typeHintBuilder = this.types.get(type);
return (typeHintBuilder != null ? typeHintBuilder.build() : null);
}
@@ -70,8 +70,7 @@ public class ReflectionHints {
* @param type the type to inspect
* @return the reflection hints for this type, or {@code null}
*/
@Nullable
public TypeHint getTypeHint(Class<?> type) {
public @Nullable TypeHint getTypeHint(Class<?> type) {
return getTypeHint(TypeReference.of(type));
}

View File

@@ -16,7 +16,8 @@
package org.springframework.aot.hint;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -35,8 +36,7 @@ final class ReflectionTypeReference extends AbstractTypeReference {
this.type = type;
}
@Nullable
private static TypeReference getEnclosingClass(Class<?> type) {
private static @Nullable TypeReference getEnclosingClass(Class<?> type) {
Class<?> candidate = (type.isArray() ? type.componentType().getEnclosingClass() :
type.getEnclosingClass());
return (candidate != null ? new ReflectionTypeReference(candidate) : null);

View File

@@ -19,7 +19,7 @@ package org.springframework.aot.hint;
import java.util.Objects;
import java.util.ResourceBundle;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A hint that describes the need to access a {@link ResourceBundle}.
@@ -32,8 +32,7 @@ public final class ResourceBundleHint implements ConditionalHint {
private final String baseName;
@Nullable
private final TypeReference reachableType;
private final @Nullable TypeReference reachableType;
ResourceBundleHint(Builder builder) {
@@ -49,9 +48,8 @@ public final class ResourceBundleHint implements ConditionalHint {
return this.baseName;
}
@Nullable
@Override
public TypeReference getReachableType() {
public @Nullable TypeReference getReachableType() {
return this.reachableType;
}
@@ -74,8 +72,7 @@ public final class ResourceBundleHint implements ConditionalHint {
private String baseName;
@Nullable
private TypeReference reachableType;
private @Nullable TypeReference reachableType;
Builder(String baseName) {
this.baseName = baseName;

View File

@@ -24,9 +24,10 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* Gather the need for resources available at runtime.

View File

@@ -18,7 +18,8 @@ package org.springframework.aot.hint;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
@@ -58,8 +59,7 @@ public final class ResourcePatternHint implements ConditionalHint {
private final String pattern;
@Nullable
private final TypeReference reachableType;
private final @Nullable TypeReference reachableType;
ResourcePatternHint(String pattern, @Nullable TypeReference reachableType) {
@@ -86,9 +86,8 @@ public final class ResourcePatternHint implements ConditionalHint {
return PATH_MATCHER.match(this.pattern, path);
}
@Nullable
@Override
public TypeReference getReachableType() {
public @Nullable TypeReference getReachableType() {
return this.reachableType;
}

View File

@@ -22,7 +22,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A collection of {@link ResourcePatternHint} describing whether resources should

View File

@@ -16,7 +16,7 @@
package org.springframework.aot.hint;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Contract for registering {@link RuntimeHints} based on the {@link ClassLoader}

View File

@@ -22,7 +22,7 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Gather the need for Java serialization at runtime.

View File

@@ -20,7 +20,8 @@ import java.util.List;
import javax.lang.model.SourceVersion;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -34,8 +35,7 @@ final class SimpleTypeReference extends AbstractTypeReference {
private static final List<String> PRIMITIVE_NAMES = List.of("boolean", "byte",
"short", "int", "long", "char", "float", "double", "void");
@Nullable
private String canonicalName;
private @Nullable String canonicalName;
SimpleTypeReference(String packageName, String simpleName, @Nullable TypeReference enclosingType) {
super(packageName, simpleName, enclosingType);

View File

@@ -27,7 +27,8 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -42,8 +43,7 @@ public final class TypeHint implements ConditionalHint {
private final TypeReference type;
@Nullable
private final TypeReference reachableType;
private final @Nullable TypeReference reachableType;
private final Set<FieldHint> fields;
@@ -83,9 +83,8 @@ public final class TypeHint implements ConditionalHint {
return this.type;
}
@Nullable
@Override
public TypeReference getReachableType() {
public @Nullable TypeReference getReachableType() {
return this.reachableType;
}
@@ -144,8 +143,7 @@ public final class TypeHint implements ConditionalHint {
private final TypeReference type;
@Nullable
private TypeReference reachableType;
private @Nullable TypeReference reachableType;
private final Set<String> fields = new HashSet<>();

View File

@@ -19,7 +19,7 @@ package org.springframework.aot.hint;
import java.util.Arrays;
import java.util.List;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Type abstraction that can be used to refer to types that are not available as
@@ -62,8 +62,7 @@ public interface TypeReference extends Comparable<TypeReference> {
* does not have an enclosing type.
* @return the enclosing type, if any
*/
@Nullable
TypeReference getEnclosingType();
@Nullable TypeReference getEnclosingType();
/**
* Create an instance based on the specified type.

View File

@@ -24,11 +24,11 @@ import java.util.Objects;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -80,8 +80,7 @@ public class RegisterReflectionReflectiveProcessor implements ReflectiveProcesso
hints.registerType(target, type -> type.withMembers(memberCategories));
}
@Nullable
private Class<?> loadClass(String className) {
private @Nullable Class<?> loadClass(String className) {
try {
return ClassUtils.forName(className, getClass().getClassLoader());
}

View File

@@ -1,9 +1,7 @@
/**
* Annotation support for runtime hints.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.hint.annotation;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -2,9 +2,7 @@
* Support for registering the need for reflection, resources, java
* serialization and proxies at runtime.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.hint;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -26,6 +26,8 @@ import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ExecutableHint;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
@@ -34,7 +36,6 @@ import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeHint;
import org.springframework.aot.hint.TypeReference;
import org.springframework.core.MethodIntrospector;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -203,8 +204,7 @@ public class ReflectionHintsPredicates {
this.type = type;
}
@Nullable
private TypeHint getTypeHint(RuntimeHints hints) {
private @Nullable TypeHint getTypeHint(RuntimeHints hints) {
return hints.reflection().getTypeHint(this.type);
}
@@ -373,8 +373,7 @@ public class ReflectionHintsPredicates {
private final Field field;
@Nullable
private ExecutableMode executableMode;
private @Nullable ExecutableMode executableMode;
FieldHintPredicate(Field field) {
this.field = field;

View File

@@ -1,9 +1,7 @@
/**
* Predicate support for runtime hints.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.hint.predicate;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -20,8 +20,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ResourceHints;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;

View File

@@ -16,10 +16,11 @@
package org.springframework.aot.hint.support;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.lang.Nullable;
/**
* {@link RuntimeHintsRegistrar} to register hints for {@link org.springframework.core.KotlinDetector}.

View File

@@ -20,13 +20,14 @@ import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.lang.Nullable;
/**
* {@link RuntimeHintsRegistrar} to register hints for popular conventions in

View File

@@ -16,11 +16,12 @@
package org.springframework.aot.hint.support;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.lang.Nullable;
/**
* {@link RuntimeHintsRegistrar} for {@link PathMatchingResourcePatternResolver}.

View File

@@ -21,13 +21,13 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.log.LogMessage;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -90,8 +90,7 @@ class SpringFactoriesLoaderRuntimeHints implements RuntimeHintsRegistrar {
}
}
@Nullable
private Class<?> resolveClassName(ClassLoader classLoader, String factoryClassName) {
private @Nullable Class<?> resolveClassName(ClassLoader classLoader, String factoryClassName) {
try {
Class<?> clazz = ClassUtils.resolveClassName(factoryClassName, classLoader);
// Force resolution of all constructors to cache

View File

@@ -16,9 +16,10 @@
package org.springframework.aot.hint.support;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.lang.Nullable;
/**
* {@link RuntimeHintsRegistrar} to register hints for {@link org.springframework.core.SpringProperties}.

View File

@@ -1,9 +1,7 @@
/**
* Convenience classes for using runtime hints.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.hint.support;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -23,7 +23,7 @@ import java.io.Writer;
import java.nio.file.Path;
import java.util.function.Consumer;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A {@link NativeConfigurationWriter} implementation that writes the
@@ -38,11 +38,9 @@ public class FileNativeConfigurationWriter extends NativeConfigurationWriter {
private final Path basePath;
@Nullable
private final String groupId;
private final @Nullable String groupId;
@Nullable
private final String artifactId;
private final @Nullable String artifactId;
public FileNativeConfigurationWriter(Path basePath) {
this(basePath, null, null);

View File

@@ -26,6 +26,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ConditionalHint;
import org.springframework.aot.hint.ExecutableHint;
import org.springframework.aot.hint.ExecutableMode;
@@ -36,7 +38,6 @@ import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeHint;
import org.springframework.aot.hint.TypeReference;
import org.springframework.lang.Nullable;
/**
* Collect {@link ReflectionHints} as map attributes ready for JSON serialization for the GraalVM

View File

@@ -1,9 +1,7 @@
/**
* GraalVM native image features, not part of Spring Framework public API.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.nativex.feature;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,9 +1,7 @@
/**
* Support for generating GraalVM native configuration from runtime hints.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.nativex;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,9 +1,7 @@
/**
* GraalVM native image substitutions, not part of Spring Framework public API.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot.nativex.substitution;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,9 +1,7 @@
/**
* Core package for Spring AOT infrastructure.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.aot;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -18,7 +18,8 @@ package org.springframework.core;
import java.util.function.Function;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -48,8 +49,7 @@ public interface AttributeAccessor {
* @param name the unique attribute key
* @return the current value of the attribute, if any
*/
@Nullable
Object getAttribute(String name);
@Nullable Object getAttribute(String name);
/**
* Compute a new value for the attribute identified by {@code name} if
@@ -89,8 +89,7 @@ public interface AttributeAccessor {
* @param name the unique attribute key
* @return the last value of the attribute, if any
*/
@Nullable
Object removeAttribute(String name);
@Nullable Object removeAttribute(String name);
/**
* Return {@code true} if the attribute identified by {@code name} exists.

View File

@@ -21,7 +21,8 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -55,8 +56,7 @@ public abstract class AttributeAccessorSupport implements AttributeAccessor, Ser
}
@Override
@Nullable
public Object getAttribute(String name) {
public @Nullable Object getAttribute(String name) {
Assert.notNull(name, "Name must not be null");
return this.attributes.get(name);
}
@@ -73,8 +73,7 @@ public abstract class AttributeAccessorSupport implements AttributeAccessor, Ser
}
@Override
@Nullable
public Object removeAttribute(String name) {
public @Nullable Object removeAttribute(String name) {
Assert.notNull(name, "Name must not be null");
return this.attributes.remove(name);
}

View File

@@ -24,7 +24,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
@@ -148,8 +149,7 @@ public final class BridgeMethodResolver {
* @param bridgeMethod the bridge method
* @return the bridged method, or {@code null} if none found
*/
@Nullable
private static Method searchCandidates(List<Method> candidateMethods, Method bridgeMethod) {
private static @Nullable Method searchCandidates(List<Method> candidateMethods, Method bridgeMethod) {
if (candidateMethods.isEmpty()) {
return null;
}
@@ -215,8 +215,7 @@ public final class BridgeMethodResolver {
* matches that of the supplied bridge method.
* @throws IllegalStateException if the generic declaration cannot be found
*/
@Nullable
private static Method findGenericDeclaration(Method bridgeMethod) {
private static @Nullable Method findGenericDeclaration(Method bridgeMethod) {
if (!bridgeMethod.isBridge()) {
return bridgeMethod;
}
@@ -235,8 +234,7 @@ public final class BridgeMethodResolver {
return searchInterfaces(interfaces, bridgeMethod);
}
@Nullable
private static Method searchInterfaces(Class<?>[] interfaces, Method bridgeMethod) {
private static @Nullable Method searchInterfaces(Class<?>[] interfaces, Method bridgeMethod) {
for (Class<?> ifc : interfaces) {
Method method = searchForMatch(ifc, bridgeMethod);
if (method != null && !method.isBridge()) {
@@ -257,8 +255,7 @@ public final class BridgeMethodResolver {
* that of the supplied {@link Method}, then this matching {@link Method} is returned,
* otherwise {@code null} is returned.
*/
@Nullable
private static Method searchForMatch(Class<?> type, Method bridgeMethod) {
private static @Nullable Method searchForMatch(Class<?> type, Method bridgeMethod) {
try {
return type.getDeclaredMethod(bridgeMethod.getName(), bridgeMethod.getParameterTypes());
}

View File

@@ -36,7 +36,8 @@ import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -349,8 +350,7 @@ public final class CollectionFactory {
public static Properties createStringAdaptingProperties() {
return new SortedProperties(false) {
@Override
@Nullable
public String getProperty(String key) {
public @Nullable String getProperty(String key) {
Object value = get(key);
return (value != null ? value.toString() : null);
}

View File

@@ -22,7 +22,8 @@ import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -35,8 +36,7 @@ import org.springframework.util.ClassUtils;
*/
public class ConfigurableObjectInputStream extends ObjectInputStream {
@Nullable
private final ClassLoader classLoader;
private final @Nullable ClassLoader classLoader;
private final boolean acceptProxyClasses;
@@ -144,8 +144,7 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
* <p>The default implementation simply returns {@code null}, indicating
* that no specific fallback is available.
*/
@Nullable
protected ClassLoader getFallbackClassLoader() throws IOException {
protected @Nullable ClassLoader getFallbackClassLoader() throws IOException {
return null;
}

View File

@@ -23,7 +23,8 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

View File

@@ -21,7 +21,8 @@ import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

View File

@@ -41,11 +41,11 @@ import kotlinx.coroutines.GlobalScope;
import kotlinx.coroutines.flow.Flow;
import kotlinx.coroutines.reactor.MonoKt;
import kotlinx.coroutines.reactor.ReactorFlowKt;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

View File

@@ -19,7 +19,8 @@ package org.springframework.core;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -25,7 +25,8 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
@@ -90,8 +91,7 @@ public final class GenericTypeResolver {
* @return the resolved parameter type of the method return type, or {@code null}
* if not resolvable or if the single argument is of type {@link WildcardType}.
*/
@Nullable
public static Class<?> resolveReturnTypeArgument(Method method, Class<?> genericType) {
public static @Nullable Class<?> resolveReturnTypeArgument(Method method, Class<?> genericType) {
Assert.notNull(method, "Method must not be null");
ResolvableType resolvableType = ResolvableType.forMethodReturnType(method).as(genericType);
if (!resolvableType.hasGenerics() || resolvableType.getType() instanceof WildcardType) {
@@ -108,8 +108,7 @@ public final class GenericTypeResolver {
* @param genericType the generic interface or superclass to resolve the type argument from
* @return the resolved type of the argument, or {@code null} if not resolvable
*/
@Nullable
public static Class<?> resolveTypeArgument(Class<?> clazz, Class<?> genericType) {
public static @Nullable Class<?> resolveTypeArgument(Class<?> clazz, Class<?> genericType) {
ResolvableType resolvableType = ResolvableType.forClass(clazz).as(genericType);
if (!resolvableType.hasGenerics()) {
return null;
@@ -117,8 +116,7 @@ public final class GenericTypeResolver {
return getSingleGeneric(resolvableType);
}
@Nullable
private static Class<?> getSingleGeneric(ResolvableType resolvableType) {
private static @Nullable Class<?> getSingleGeneric(ResolvableType resolvableType) {
Assert.isTrue(resolvableType.getGenerics().length == 1,
() -> "Expected 1 type argument on generic interface [" + resolvableType +
"] but found " + resolvableType.getGenerics().length);
@@ -135,8 +133,7 @@ public final class GenericTypeResolver {
* @return the resolved type of each argument, with the array size matching the
* number of actual type arguments, or {@code null} if not resolvable
*/
@Nullable
public static Class<?>[] resolveTypeArguments(Class<?> clazz, Class<?> genericType) {
public static Class<?> @Nullable [] resolveTypeArguments(Class<?> clazz, Class<?> genericType) {
ResolvableType type = ResolvableType.forClass(clazz).as(genericType);
if (!type.hasGenerics() || !type.hasResolvableGenerics()) {
return null;
@@ -295,8 +292,7 @@ public final class GenericTypeResolver {
}
@Override
@Nullable
public ResolvableType resolveVariable(TypeVariable<?> variable) {
public @Nullable ResolvableType resolveVariable(TypeVariable<?> variable) {
Type type = this.typeVariableMap.get(variable);
return (type != null ? ResolvableType.forType(type) : null);
}

View File

@@ -19,7 +19,8 @@ package org.springframework.core;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -32,11 +33,9 @@ import org.springframework.util.ClassUtils;
@SuppressWarnings("unchecked")
public abstract class KotlinDetector {
@Nullable
private static final Class<? extends Annotation> kotlinMetadata;
private static final @Nullable Class<? extends Annotation> kotlinMetadata;
@Nullable
private static final Class<? extends Annotation> kotlinJvmInline;
private static final @Nullable Class<? extends Annotation> kotlinJvmInline;
// For ConstantFieldFeature compliance, otherwise could be deduced from kotlinMetadata
private static final boolean kotlinPresent;

View File

@@ -23,8 +23,7 @@ import java.util.List;
import kotlin.reflect.KFunction;
import kotlin.reflect.KParameter;
import kotlin.reflect.jvm.ReflectJvmMapping;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* {@link ParameterNameDiscoverer} implementation which uses Kotlin's reflection facilities
@@ -41,8 +40,7 @@ import org.springframework.lang.Nullable;
public class KotlinReflectionParameterNameDiscoverer implements ParameterNameDiscoverer {
@Override
@Nullable
public String[] getParameterNames(Method method) {
public @Nullable String @Nullable [] getParameterNames(Method method) {
if (!KotlinDetector.isKotlinType(method.getDeclaringClass())) {
return null;
}
@@ -57,8 +55,7 @@ public class KotlinReflectionParameterNameDiscoverer implements ParameterNameDis
}
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
public @Nullable String @Nullable [] getParameterNames(Constructor<?> ctor) {
if (ctor.getDeclaringClass().isEnum() || !KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
return null;
}
@@ -72,8 +69,7 @@ public class KotlinReflectionParameterNameDiscoverer implements ParameterNameDis
}
}
@Nullable
private String[] getParameterNames(List<KParameter> parameters) {
private @Nullable String @Nullable [] getParameterNames(List<KParameter> parameters) {
String[] parameterNames = parameters.stream()
// Extension receivers of extension methods must be included as they appear as normal method parameters in Java
.filter(p -> KParameter.Kind.VALUE.equals(p.getKind()) || KParameter.Kind.EXTENSION_RECEIVER.equals(p.getKind()))

View File

@@ -18,7 +18,8 @@ package org.springframework.core;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -33,8 +34,7 @@ public final class MethodClassKey implements Comparable<MethodClassKey> {
private final Method method;
@Nullable
private final Class<?> targetClass;
private final @Nullable Class<?> targetClass;
/**

View File

@@ -23,7 +23,8 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -155,8 +156,7 @@ public final class MethodIntrospector {
* @return non-null metadata to be associated with a method if there is a match,
* or {@code null} for no match
*/
@Nullable
T inspect(Method method);
@Nullable T inspect(Method method);
}
}

View File

@@ -38,8 +38,8 @@ import kotlin.Unit;
import kotlin.reflect.KFunction;
import kotlin.reflect.KParameter;
import kotlin.reflect.jvm.ReflectJvmMapping;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -71,36 +71,27 @@ public class MethodParameter {
private final int parameterIndex;
@Nullable
private volatile Parameter parameter;
private volatile @Nullable Parameter parameter;
private int nestingLevel;
/** Map from Integer level to Integer type index. */
@Nullable
Map<Integer, Integer> typeIndexesPerLevel;
@Nullable Map<Integer, Integer> typeIndexesPerLevel;
/** The containing class. Could also be supplied by overriding {@link #getContainingClass()} */
@Nullable
private volatile Class<?> containingClass;
private volatile @Nullable Class<?> containingClass;
@Nullable
private volatile Class<?> parameterType;
private volatile @Nullable Class<?> parameterType;
@Nullable
private volatile Type genericParameterType;
private volatile @Nullable Type genericParameterType;
@Nullable
private volatile Annotation[] parameterAnnotations;
private volatile Annotation @Nullable [] parameterAnnotations;
@Nullable
private volatile ParameterNameDiscoverer parameterNameDiscoverer;
private volatile @Nullable ParameterNameDiscoverer parameterNameDiscoverer;
@Nullable
volatile String parameterName;
volatile @Nullable String parameterName;
@Nullable
private volatile MethodParameter nestedMethodParameter;
private volatile @Nullable MethodParameter nestedMethodParameter;
/**
@@ -197,8 +188,7 @@ public class MethodParameter {
* <p>Note: Either Method or Constructor is available.
* @return the Method, or {@code null} if none
*/
@Nullable
public Method getMethod() {
public @Nullable Method getMethod() {
return (this.executable instanceof Method method ? method : null);
}
@@ -207,8 +197,7 @@ public class MethodParameter {
* <p>Note: Either Method or Constructor is available.
* @return the Constructor, or {@code null} if none
*/
@Nullable
public Constructor<?> getConstructor() {
public @Nullable Constructor<?> getConstructor() {
return (this.executable instanceof Constructor<?> constructor ? constructor : null);
}
@@ -331,8 +320,7 @@ public class MethodParameter {
* if none specified (indicating the default type index)
* @see #getNestingLevel()
*/
@Nullable
public Integer getTypeIndexForCurrentLevel() {
public @Nullable Integer getTypeIndexForCurrentLevel() {
return getTypeIndexForLevel(this.nestingLevel);
}
@@ -342,8 +330,7 @@ public class MethodParameter {
* @return the corresponding type index, or {@code null}
* if none specified (indicating the default type index)
*/
@Nullable
public Integer getTypeIndexForLevel(int nestingLevel) {
public @Nullable Integer getTypeIndexForLevel(int nestingLevel) {
return getTypeIndexesPerLevel().get(nestingLevel);
}
@@ -616,8 +603,7 @@ public class MethodParameter {
* @param annotationType the annotation type to look for
* @return the annotation object, or {@code null} if not found
*/
@Nullable
public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
public <A extends Annotation> @Nullable A getMethodAnnotation(Class<A> annotationType) {
A annotation = getAnnotatedElement().getAnnotation(annotationType);
return (annotation != null ? adaptAnnotation(annotation) : null);
}
@@ -669,8 +655,7 @@ public class MethodParameter {
* @return the annotation object, or {@code null} if not found
*/
@SuppressWarnings("unchecked")
@Nullable
public <A extends Annotation> A getParameterAnnotation(Class<A> annotationType) {
public <A extends Annotation> @Nullable A getParameterAnnotation(Class<A> annotationType) {
Annotation[] anns = getParameterAnnotations();
for (Annotation ann : anns) {
if (annotationType.isInstance(ann)) {
@@ -706,8 +691,7 @@ public class MethodParameter {
* {@link #initParameterNameDiscovery ParameterNameDiscoverer}
* has been set to begin with)
*/
@Nullable
public String getParameterName() {
public @Nullable String getParameterName() {
if (this.parameterIndex < 0) {
return null;
}
@@ -882,8 +866,7 @@ public class MethodParameter {
*/
private static class FieldAwareConstructorParameter extends MethodParameter {
@Nullable
private volatile Annotation[] combinedAnnotations;
private volatile Annotation @Nullable [] combinedAnnotations;
public FieldAwareConstructorParameter(Constructor<?> constructor, int parameterIndex, String fieldName) {
super(constructor, parameterIndex);

View File

@@ -16,7 +16,7 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A common delegate for detecting a GraalVM native image environment.
@@ -27,8 +27,7 @@ import org.springframework.lang.Nullable;
public abstract class NativeDetector {
// See https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java
@Nullable
private static final String imageCode = System.getProperty("org.graalvm.nativeimage.imagecode");
private static final @Nullable String imageCode = System.getProperty("org.graalvm.nativeimage.imagecode");
private static final boolean inNativeImage = (imageCode != null);

View File

@@ -16,7 +16,7 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Handy class for wrapping checked {@code Exceptions} with a root cause.
@@ -60,8 +60,7 @@ public abstract class NestedCheckedException extends Exception {
* Retrieve the innermost cause of this exception, if any.
* @return the innermost exception, or {@code null} if none
*/
@Nullable
public Throwable getRootCause() {
public @Nullable Throwable getRootCause() {
return NestedExceptionUtils.getRootCause(this);
}

View File

@@ -16,7 +16,7 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Helper class for implementing exception classes which are capable of
@@ -41,8 +41,7 @@ public abstract class NestedExceptionUtils {
* with selective inclusion of cause messages
*/
@Deprecated(since = "6.0")
@Nullable
public static String buildMessage(@Nullable String message, @Nullable Throwable cause) {
public static @Nullable String buildMessage(@Nullable String message, @Nullable Throwable cause) {
if (cause == null) {
return message;
}
@@ -60,8 +59,7 @@ public abstract class NestedExceptionUtils {
* @return the innermost exception, or {@code null} if none
* @since 4.3.9
*/
@Nullable
public static Throwable getRootCause(@Nullable Throwable original) {
public static @Nullable Throwable getRootCause(@Nullable Throwable original) {
if (original == null) {
return null;
}

View File

@@ -16,7 +16,7 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Handy class for wrapping runtime {@code Exceptions} with a root cause.
@@ -61,8 +61,7 @@ public abstract class NestedRuntimeException extends RuntimeException {
* @return the innermost exception, or {@code null} if none
* @since 2.0
*/
@Nullable
public Throwable getRootCause() {
public @Nullable Throwable getRootCause() {
return NestedExceptionUtils.getRootCause(this);
}

View File

@@ -20,7 +20,8 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -140,8 +141,7 @@ public class OrderComparator implements Comparator<Object> {
* @param obj the object to check
* @return the order value, or {@code null} if none found
*/
@Nullable
protected Integer findOrder(Object obj) {
protected @Nullable Integer findOrder(Object obj) {
return (obj instanceof Ordered ordered ? ordered.getOrder() : null);
}
@@ -156,8 +156,7 @@ public class OrderComparator implements Comparator<Object> {
* @return the priority value, or {@code null} if none
* @since 4.1
*/
@Nullable
public Integer getPriority(Object obj) {
public @Nullable Integer getPriority(Object obj) {
return null;
}
@@ -222,8 +221,7 @@ public class OrderComparator implements Comparator<Object> {
* @param obj the object to find an order source for
* @return the order source for that object, or {@code null} if none found
*/
@Nullable
Object getOrderSource(Object obj);
@Nullable Object getOrderSource(Object obj);
}
}

View File

@@ -19,7 +19,8 @@ package org.springframework.core;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.FileCopyUtils;
/**
@@ -47,8 +48,7 @@ public class OverridingClassLoader extends DecoratingClassLoader {
}
@Nullable
private final ClassLoader overrideDelegate;
private final @Nullable ClassLoader overrideDelegate;
/**
@@ -115,8 +115,7 @@ public class OverridingClassLoader extends DecoratingClassLoader {
* @return the Class object, or {@code null} if no class defined for that name
* @throws ClassNotFoundException if the class for the given name couldn't be loaded
*/
@Nullable
protected Class<?> loadClassForOverriding(String name) throws ClassNotFoundException {
protected @Nullable Class<?> loadClassForOverriding(String name) throws ClassNotFoundException {
Class<?> result = findLoadedClass(name);
if (result == null) {
byte[] bytes = loadBytesForClass(name);
@@ -137,8 +136,7 @@ public class OverridingClassLoader extends DecoratingClassLoader {
* or {@code null} if no class defined for that name
* @throws ClassNotFoundException if the class for the given name couldn't be loaded
*/
@Nullable
protected byte[] loadBytesForClass(String name) throws ClassNotFoundException {
protected byte @Nullable [] loadBytesForClass(String name) throws ClassNotFoundException {
InputStream is = openStreamForClass(name);
if (is == null) {
return null;
@@ -161,8 +159,7 @@ public class OverridingClassLoader extends DecoratingClassLoader {
* @param name the name of the class
* @return the InputStream containing the byte code for the specified class
*/
@Nullable
protected InputStream openStreamForClass(String name) {
protected @Nullable InputStream openStreamForClass(String name) {
String internalName = name.replace('.', '/') + CLASS_FILE_SUFFIX;
return getParent().getResourceAsStream(internalName);
}

View File

@@ -19,7 +19,7 @@ package org.springframework.core;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Interface to discover parameter names for methods and constructors.
@@ -45,8 +45,7 @@ public interface ParameterNameDiscoverer {
* @return an array of parameter names if the names can be resolved,
* or {@code null} if they cannot
*/
@Nullable
String[] getParameterNames(Method method);
@Nullable String @Nullable [] getParameterNames(Method method);
/**
* Return parameter names for a constructor, or {@code null} if they cannot be determined.
@@ -57,7 +56,6 @@ public interface ParameterNameDiscoverer {
* @return an array of parameter names if the names can be resolved,
* or {@code null} if they cannot
*/
@Nullable
String[] getParameterNames(Constructor<?> ctor);
@Nullable String @Nullable [] getParameterNames(Constructor<?> ctor);
}

View File

@@ -19,7 +19,8 @@ package org.springframework.core;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -21,7 +21,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* {@link ParameterNameDiscoverer} implementation that tries several discoverer
@@ -49,10 +49,9 @@ public class PrioritizedParameterNameDiscoverer implements ParameterNameDiscover
@Override
@Nullable
public String[] getParameterNames(Method method) {
public @Nullable String @Nullable [] getParameterNames(Method method) {
for (ParameterNameDiscoverer pnd : this.parameterNameDiscoverers) {
String[] result = pnd.getParameterNames(method);
@Nullable String[] result = pnd.getParameterNames(method);
if (result != null) {
return result;
}
@@ -61,10 +60,9 @@ public class PrioritizedParameterNameDiscoverer implements ParameterNameDiscover
}
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
public @Nullable String @Nullable [] getParameterNames(Constructor<?> ctor) {
for (ParameterNameDiscoverer pnd : this.parameterNameDiscoverers) {
String[] result = pnd.getParameterNames(ctor);
@Nullable String[] result = pnd.getParameterNames(ctor);
if (result != null) {
return result;
}

View File

@@ -18,9 +18,9 @@ package org.springframework.core;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -25,6 +25,7 @@ import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.FlowAdapters;
import org.reactivestreams.Publisher;
import reactor.adapter.JdkFlowAdapter;
@@ -33,7 +34,6 @@ import reactor.blockhound.integration.BlockHoundIntegration;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
@@ -56,8 +56,7 @@ import org.springframework.util.ReflectionUtils;
*/
public class ReactiveAdapterRegistry {
@Nullable
private static volatile ReactiveAdapterRegistry sharedInstance;
private static volatile @Nullable ReactiveAdapterRegistry sharedInstance;
private static final boolean reactiveStreamsPresent;
@@ -174,8 +173,7 @@ public class ReactiveAdapterRegistry {
* Get the adapter for the given reactive type.
* @return the corresponding adapter, or {@code null} if none available
*/
@Nullable
public ReactiveAdapter getAdapter(Class<?> reactiveType) {
public @Nullable ReactiveAdapter getAdapter(Class<?> reactiveType) {
return getAdapter(reactiveType, null);
}
@@ -188,8 +186,7 @@ public class ReactiveAdapterRegistry {
* (i.e. to adapt from; may be {@code null} if the reactive type is specified)
* @return the corresponding adapter, or {@code null} if none available
*/
@Nullable
public ReactiveAdapter getAdapter(@Nullable Class<?> reactiveType, @Nullable Object source) {
public @Nullable ReactiveAdapter getAdapter(@Nullable Class<?> reactiveType, @Nullable Object source) {
if (this.adapters.isEmpty()) {
return null;
}

View File

@@ -18,7 +18,8 @@ package org.springframework.core;
import java.util.function.Supplier;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -36,8 +37,7 @@ public final class ReactiveTypeDescriptor {
private final boolean noValue;
@Nullable
private final Supplier<?> emptySupplier;
private final @Nullable Supplier<?> emptySupplier;
private final boolean deferred;

View File

@@ -34,10 +34,11 @@ import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import org.jspecify.annotations.Nullable;
import org.springframework.core.SerializableTypeWrapper.FieldTypeProvider;
import org.springframework.core.SerializableTypeWrapper.MethodParameterTypeProvider;
import org.springframework.core.SerializableTypeWrapper.TypeProvider;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
@@ -106,38 +107,29 @@ public class ResolvableType implements Serializable {
/**
* The component type for an array or {@code null} if the type should be deduced.
*/
@Nullable
private final ResolvableType componentType;
private final @Nullable ResolvableType componentType;
/**
* Optional provider for the type.
*/
@Nullable
private final TypeProvider typeProvider;
private final @Nullable TypeProvider typeProvider;
/**
* The {@code VariableResolver} to use or {@code null} if no resolver is available.
*/
@Nullable
private final VariableResolver variableResolver;
private final @Nullable VariableResolver variableResolver;
@Nullable
private final Integer hash;
private final @Nullable Integer hash;
@Nullable
private Class<?> resolved;
private @Nullable Class<?> resolved;
@Nullable
private volatile ResolvableType superType;
private volatile @Nullable ResolvableType superType;
@Nullable
private volatile ResolvableType[] interfaces;
private volatile ResolvableType @Nullable [] interfaces;
@Nullable
private volatile ResolvableType[] generics;
private volatile ResolvableType @Nullable [] generics;
@Nullable
private volatile Boolean unresolvableGenerics;
private volatile @Nullable Boolean unresolvableGenerics;
/**
@@ -212,8 +204,7 @@ public class ResolvableType implements Serializable {
* Return the underlying Java {@link Class} being managed, if available;
* otherwise {@code null}.
*/
@Nullable
public Class<?> getRawClass() {
public @Nullable Class<?> getRawClass() {
if (this.type == this.resolved) {
return this.resolved;
}
@@ -759,7 +750,7 @@ public class ResolvableType implements Serializable {
* @see #resolveGeneric(int...)
* @see #resolveGenerics()
*/
public ResolvableType getGeneric(@Nullable int... indexes) {
public ResolvableType getGeneric(int @Nullable ... indexes) {
ResolvableType[] generics = getGenerics();
if (indexes == null || indexes.length == 0) {
return (generics.length == 0 ? NONE : generics[0]);
@@ -870,8 +861,7 @@ public class ResolvableType implements Serializable {
* @see #getGeneric(int...)
* @see #resolve()
*/
@Nullable
public Class<?> resolveGeneric(int... indexes) {
public @Nullable Class<?> resolveGeneric(int... indexes) {
return getGeneric(indexes).resolve();
}
@@ -888,8 +878,7 @@ public class ResolvableType implements Serializable {
* @see #resolveGeneric(int...)
* @see #resolveGenerics()
*/
@Nullable
public Class<?> resolve() {
public @Nullable Class<?> resolve() {
return this.resolved;
}
@@ -908,8 +897,7 @@ public class ResolvableType implements Serializable {
return (this.resolved != null ? this.resolved : fallback);
}
@Nullable
private Class<?> resolveClass() {
private @Nullable Class<?> resolveClass() {
if (this.type == EmptyType.INSTANCE) {
return null;
}
@@ -953,16 +941,14 @@ public class ResolvableType implements Serializable {
return NONE;
}
@Nullable
private Type resolveBounds(Type[] bounds) {
private @Nullable Type resolveBounds(Type[] bounds) {
if (bounds.length == 0 || bounds[0] == Object.class) {
return null;
}
return bounds[0];
}
@Nullable
private ResolvableType resolveVariable(TypeVariable<?> variable) {
private @Nullable ResolvableType resolveVariable(TypeVariable<?> variable) {
if (this.type instanceof TypeVariable) {
return resolveType().resolveVariable(variable);
}
@@ -1062,8 +1048,7 @@ public class ResolvableType implements Serializable {
/**
* Adapts this {@code ResolvableType} to a {@link VariableResolver}.
*/
@Nullable
VariableResolver asVariableResolver() {
@Nullable VariableResolver asVariableResolver() {
if (this == NONE) {
return null;
}
@@ -1190,7 +1175,7 @@ public class ResolvableType implements Serializable {
* @return a {@code ResolvableType} for the specific class and generics
* @see #forClassWithGenerics(Class, Class...)
*/
public static ResolvableType forClassWithGenerics(Class<?> clazz, @Nullable ResolvableType... generics) {
public static ResolvableType forClassWithGenerics(Class<?> clazz, @Nullable ResolvableType @Nullable ... generics) {
Assert.notNull(clazz, "Class must not be null");
TypeVariable<?>[] variables = clazz.getTypeParameters();
if (generics != null) {
@@ -1578,8 +1563,7 @@ public class ResolvableType implements Serializable {
* @param variable the variable to resolve
* @return the resolved variable, or {@code null} if not found
*/
@Nullable
ResolvableType resolveVariable(TypeVariable<?> variable);
@Nullable ResolvableType resolveVariable(TypeVariable<?> variable);
}
@@ -1593,8 +1577,7 @@ public class ResolvableType implements Serializable {
}
@Override
@Nullable
public ResolvableType resolveVariable(TypeVariable<?> variable) {
public @Nullable ResolvableType resolveVariable(TypeVariable<?> variable) {
return this.source.resolveVariable(variable);
}
@@ -1610,16 +1593,15 @@ public class ResolvableType implements Serializable {
private final TypeVariable<?>[] variables;
private final ResolvableType[] generics;
private final @Nullable ResolvableType[] generics;
public TypeVariablesVariableResolver(TypeVariable<?>[] variables, ResolvableType[] generics) {
public TypeVariablesVariableResolver(TypeVariable<?>[] variables, @Nullable ResolvableType[] generics) {
this.variables = variables;
this.generics = generics;
}
@Override
@Nullable
public ResolvableType resolveVariable(TypeVariable<?> variable) {
public @Nullable ResolvableType resolveVariable(TypeVariable<?> variable) {
TypeVariable<?> variableToCompare = SerializableTypeWrapper.unwrap(variable);
for (int i = 0; i < this.variables.length; i++) {
TypeVariable<?> resolvedVariable = SerializableTypeWrapper.unwrap(this.variables[i]);
@@ -1662,8 +1644,7 @@ public class ResolvableType implements Serializable {
}
@Override
@Nullable
public Type getOwnerType() {
public @Nullable Type getOwnerType() {
return null;
}
@@ -1787,8 +1768,7 @@ public class ResolvableType implements Serializable {
* @param type the source type
* @return a {@link WildcardBounds} instance or {@code null}
*/
@Nullable
public static WildcardBounds get(ResolvableType type) {
public static @Nullable WildcardBounds get(ResolvableType type) {
ResolvableType candidate = type;
while (!(candidate.getType() instanceof WildcardType || candidate.isUnresolvableTypeVariable())) {
if (candidate == NONE) {

View File

@@ -16,7 +16,7 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Any object can implement this interface to provide its actual {@link ResolvableType}.
@@ -37,7 +37,6 @@ public interface ResolvableTypeProvider {
* Return the {@link ResolvableType} describing this instance
* (or {@code null} if some sort of default should be applied instead).
*/
@Nullable
ResolvableType getResolvableType();
@Nullable ResolvableType getResolvableType();
}

View File

@@ -29,7 +29,8 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -68,8 +69,7 @@ final class SerializableTypeWrapper {
/**
* Return a {@link Serializable} variant of {@link Field#getGenericType()}.
*/
@Nullable
public static Type forField(Field field) {
public static @Nullable Type forField(Field field) {
return forTypeProvider(new FieldTypeProvider(field));
}
@@ -77,8 +77,7 @@ final class SerializableTypeWrapper {
* Return a {@link Serializable} variant of
* {@link MethodParameter#getGenericParameterType()}.
*/
@Nullable
public static Type forMethodParameter(MethodParameter methodParameter) {
public static @Nullable Type forMethodParameter(MethodParameter methodParameter) {
return forTypeProvider(new MethodParameterTypeProvider(methodParameter));
}
@@ -101,8 +100,7 @@ final class SerializableTypeWrapper {
* <p>If type artifacts are generally not serializable in the current runtime
* environment, this delegate will simply return the original {@code Type} as-is.
*/
@Nullable
static Type forTypeProvider(TypeProvider provider) {
static @Nullable Type forTypeProvider(TypeProvider provider) {
Type providedType = provider.getType();
if (providedType == null || providedType instanceof Serializable) {
// No serializable type wrapping necessary (for example, for java.lang.Class)
@@ -154,15 +152,13 @@ final class SerializableTypeWrapper {
/**
* Return the (possibly non {@link Serializable}) {@link Type}.
*/
@Nullable
Type getType();
@Nullable Type getType();
/**
* Return the source of the type, or {@code null} if not known.
* <p>The default implementation returns {@code null}.
*/
@Nullable
default Object getSource() {
default @Nullable Object getSource() {
return null;
}
}
@@ -183,8 +179,7 @@ final class SerializableTypeWrapper {
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
public @Nullable Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "equals" -> {
Object other = args[0];
@@ -273,8 +268,7 @@ final class SerializableTypeWrapper {
@SuppressWarnings("serial")
static class MethodParameterTypeProvider implements TypeProvider {
@Nullable
private final String methodName;
private final @Nullable String methodName;
private final Class<?>[] parameterTypes;
@@ -337,8 +331,7 @@ final class SerializableTypeWrapper {
private transient Method method;
@Nullable
private transient volatile Object result;
private transient volatile @Nullable Object result;
public MethodInvokeTypeProvider(TypeProvider provider, Method method, int index) {
this.provider = provider;
@@ -349,8 +342,7 @@ final class SerializableTypeWrapper {
}
@Override
@Nullable
public Type getType() {
public @Nullable Type getType() {
Object result = this.result;
if (result == null) {
// Lazy invocation of the target method on the provided type
@@ -362,8 +354,7 @@ final class SerializableTypeWrapper {
}
@Override
@Nullable
public Object getSource() {
public @Nullable Object getSource() {
return null;
}

View File

@@ -18,7 +18,7 @@ package org.springframework.core;
import java.security.ProtectionDomain;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Interface to be implemented by a reloading-aware ClassLoader

View File

@@ -30,7 +30,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Specialization of {@link Properties} that sorts properties alphanumerically

View File

@@ -21,7 +21,7 @@ import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Static holder for local Spring properties, i.e. defined at the Spring library level.
@@ -97,8 +97,7 @@ public final class SpringProperties {
* @param key the property key
* @return the associated property value, or {@code null} if none found
*/
@Nullable
public static String getProperty(String key) {
public static @Nullable String getProperty(String key) {
String value = localProperties.getProperty(key);
if (value == null) {
try {

View File

@@ -16,7 +16,7 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Class that exposes the Spring version. Fetches the
@@ -42,8 +42,7 @@ public final class SpringVersion {
* or {@code null} if it cannot be determined.
* @see Package#getImplementationVersion()
*/
@Nullable
public static String getVersion() {
public static @Nullable String getVersion() {
Package pkg = SpringVersion.class.getPackage();
return (pkg != null ? pkg.getImplementationVersion() : null);
}

View File

@@ -20,7 +20,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* {@link ParameterNameDiscoverer} implementation which uses JDK 8's reflection facilities
@@ -39,19 +39,16 @@ import org.springframework.lang.Nullable;
public class StandardReflectionParameterNameDiscoverer implements ParameterNameDiscoverer {
@Override
@Nullable
public String[] getParameterNames(Method method) {
public @Nullable String @Nullable [] getParameterNames(Method method) {
return getParameterNames(method.getParameters());
}
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
public @Nullable String @Nullable [] getParameterNames(Constructor<?> ctor) {
return getParameterNames(ctor.getParameters());
}
@Nullable
private String[] getParameterNames(Parameter[] parameters) {
private String @Nullable [] getParameterNames(Parameter[] parameters) {
String[] parameterNames = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
Parameter param = parameters[i];

View File

@@ -21,7 +21,8 @@ import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Predicate;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -34,8 +35,7 @@ import org.springframework.util.Assert;
*/
abstract class AbstractMergedAnnotation<A extends Annotation> implements MergedAnnotation<A> {
@Nullable
private volatile A synthesizedAnnotation;
private volatile @Nullable A synthesizedAnnotation;
@Override
@@ -230,8 +230,7 @@ abstract class AbstractMergedAnnotation<A extends Annotation> implements MergedA
* @throws IllegalArgumentException if the source type is not compatible
* @throws NoSuchElementException if the value is required but not found
*/
@Nullable
protected abstract <T> T getAttributeValue(String attributeName, Class<T> type);
protected abstract <T> @Nullable T getAttributeValue(String attributeName, Class<T> type);
/**
* Factory method used to create the synthesized annotation.

View File

@@ -24,10 +24,11 @@ import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.annotation.MergedAnnotation.Adapt;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
/**
@@ -243,8 +244,7 @@ public abstract class AnnotatedElementUtils {
* @see #getMergedAnnotation(AnnotatedElement, Class)
* @see #findMergedAnnotation(AnnotatedElement, Class)
*/
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(
public static @Nullable AnnotationAttributes getMergedAnnotationAttributes(
AnnotatedElement element, Class<? extends Annotation> annotationType) {
MergedAnnotation<?> mergedAnnotation = getAnnotations(element)
@@ -270,8 +270,7 @@ public abstract class AnnotatedElementUtils {
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see #getAllAnnotationAttributes(AnnotatedElement, String)
*/
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
public static @Nullable AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
String annotationName) {
return getMergedAnnotationAttributes(element, annotationName, false, false);
@@ -303,8 +302,7 @@ public abstract class AnnotatedElementUtils {
* @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
* @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
public static @Nullable AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
MergedAnnotation<?> mergedAnnotation = getAnnotations(element)
@@ -326,8 +324,7 @@ public abstract class AnnotatedElementUtils {
* @since 4.2
* @see #findMergedAnnotation(AnnotatedElement, Class)
*/
@Nullable
public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
public static <A extends Annotation> @Nullable A getMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
// Shortcut: directly present on the element, with no merging needed?
if (AnnotationFilter.PLAIN.matches(annotationType) ||
AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
@@ -481,8 +478,7 @@ public abstract class AnnotatedElementUtils {
* attributes from all annotations found, or {@code null} if not found
* @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
@Nullable
public static MultiValueMap<String, Object> getAllAnnotationAttributes(
public static @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(
AnnotatedElement element, String annotationName) {
return getAllAnnotationAttributes(element, annotationName, false, false);
@@ -506,8 +502,7 @@ public abstract class AnnotatedElementUtils {
* @return a {@link MultiValueMap} keyed by attribute name, containing the annotation
* attributes from all annotations found, or {@code null} if not found
*/
@Nullable
public static MultiValueMap<String, Object> getAllAnnotationAttributes(AnnotatedElement element,
public static @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(AnnotatedElement element,
String annotationName, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) {
Adapt[] adaptations = Adapt.values(classValuesAsString, nestedAnnotationsAsMap);
@@ -568,8 +563,7 @@ public abstract class AnnotatedElementUtils {
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
@Nullable
public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
public static @Nullable AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
Class<? extends Annotation> annotationType, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
MergedAnnotation<?> mergedAnnotation = findAnnotations(element)
@@ -604,8 +598,7 @@ public abstract class AnnotatedElementUtils {
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
@Nullable
public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
public static @Nullable AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
MergedAnnotation<?> mergedAnnotation = findAnnotations(element)
@@ -631,8 +624,7 @@ public abstract class AnnotatedElementUtils {
* @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
* @see #getMergedAnnotationAttributes(AnnotatedElement, Class)
*/
@Nullable
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
public static <A extends Annotation> @Nullable A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
// Shortcut: directly present on the element, with no merging needed?
if (AnnotationFilter.PLAIN.matches(annotationType) ||
AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
@@ -823,8 +815,7 @@ public abstract class AnnotatedElementUtils {
return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY, repeatableContainers);
}
@Nullable
private static MultiValueMap<String, Object> nullIfEmpty(MultiValueMap<String, Object> map) {
private static @Nullable MultiValueMap<String, Object> nullIfEmpty(MultiValueMap<String, Object> map) {
return (map.isEmpty() ? null : map);
}
@@ -832,8 +823,7 @@ public abstract class AnnotatedElementUtils {
return Comparator.<MergedAnnotation<A>> comparingInt(MergedAnnotation::getAggregateIndex).reversed();
}
@Nullable
private static AnnotationAttributes getAnnotationAttributes(MergedAnnotation<?> annotation,
private static @Nullable AnnotationAttributes getAnnotationAttributes(MergedAnnotation<?> annotation,
boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
if (!annotation.isPresent()) {
@@ -856,8 +846,7 @@ public abstract class AnnotatedElementUtils {
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
public <T extends Annotation> @Nullable T getAnnotation(Class<T> annotationClass) {
for (Annotation annotation : this.annotations) {
if (annotation.annotationType() == annotationClass) {
return (T) annotation;

View File

@@ -22,11 +22,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -52,8 +53,7 @@ public class AnnotatedMethod {
private final MethodParameter[] parameters;
@Nullable
private volatile List<Annotation[][]> inheritedParameterAnnotations;
private volatile @Nullable List<Annotation[][]> inheritedParameterAnnotations;
/**
@@ -148,8 +148,7 @@ public class AnnotatedMethod {
* @return the annotation, or {@code null} if none found
* @see AnnotatedElementUtils#findMergedAnnotation
*/
@Nullable
public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
public <A extends Annotation> @Nullable A getMethodAnnotation(Class<A> annotationType) {
return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType);
}
@@ -231,8 +230,7 @@ public class AnnotatedMethod {
// Support methods for use in subclass variants
@Nullable
protected static Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) {
protected static @Nullable Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) {
if (!ObjectUtils.isEmpty(providedArgs)) {
for (Object providedArg : providedArgs) {
if (parameter.getParameterType().isInstance(providedArg)) {
@@ -254,8 +252,7 @@ public class AnnotatedMethod {
*/
protected class AnnotatedMethodParameter extends SynthesizingMethodParameter {
@Nullable
private volatile Annotation[] combinedAnnotations;
private volatile Annotation @Nullable [] combinedAnnotations;
public AnnotatedMethodParameter(int index) {
super(AnnotatedMethod.this.getBridgedMethod(), index);
@@ -267,8 +264,7 @@ public class AnnotatedMethod {
}
@Override
@NonNull
public Method getMethod() {
public @NonNull Method getMethod() {
return AnnotatedMethod.this.getBridgedMethod();
}
@@ -278,8 +274,7 @@ public class AnnotatedMethod {
}
@Override
@Nullable
public <T extends Annotation> T getMethodAnnotation(Class<T> annotationType) {
public <T extends Annotation> @Nullable T getMethodAnnotation(Class<T> annotationType) {
return AnnotatedMethod.this.getMethodAnnotation(annotationType);
}
@@ -335,8 +330,7 @@ public class AnnotatedMethod {
*/
private class ReturnValueMethodParameter extends AnnotatedMethodParameter {
@Nullable
private final Class<?> returnValueType;
private final @Nullable Class<?> returnValueType;
public ReturnValueMethodParameter(@Nullable Object returnValue) {
super(-1);

View File

@@ -22,7 +22,8 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -48,8 +49,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
private static final String UNKNOWN = "unknown";
@Nullable
private final Class<? extends Annotation> annotationType;
private final @Nullable Class<? extends Annotation> annotationType;
final String displayName;
@@ -147,8 +147,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
}
@SuppressWarnings("unchecked")
@Nullable
private static Class<? extends Annotation> getAnnotationType(String annotationType, @Nullable ClassLoader classLoader) {
private static @Nullable Class<? extends Annotation> getAnnotationType(String annotationType, @Nullable ClassLoader classLoader) {
if (classLoader != null) {
try {
return (Class<? extends Annotation>) classLoader.loadClass(annotationType);
@@ -166,8 +165,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
* @return the annotation type, or {@code null} if unknown
* @since 4.2
*/
@Nullable
public Class<? extends Annotation> annotationType() {
public @Nullable Class<? extends Annotation> annotationType() {
return this.annotationType;
}
@@ -412,8 +410,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
* to the {@link #AnnotationAttributes(Map)} constructor.
* @param map original source of annotation attribute <em>key-value</em> pairs
*/
@Nullable
public static AnnotationAttributes fromMap(@Nullable Map<String, Object> map) {
public static @Nullable AnnotationAttributes fromMap(@Nullable Map<String, Object> map) {
if (map == null) {
return null;
}

View File

@@ -20,10 +20,11 @@ import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.core.DecoratingProxy;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Nullable;
/**
* {@code AnnotationAwareOrderComparator} is an extension of
@@ -59,8 +60,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
* check in the superclass.
*/
@Override
@Nullable
protected Integer findOrder(Object obj) {
protected @Nullable Integer findOrder(Object obj) {
Integer order = super.findOrder(obj);
if (order != null) {
return order;
@@ -68,8 +68,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
return findOrderFromAnnotation(obj);
}
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
private @Nullable Integer findOrderFromAnnotation(Object obj) {
AnnotatedElement element = (obj instanceof AnnotatedElement ae ? ae : obj.getClass());
MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
@@ -86,8 +85,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
* multiple matches but only one object to be returned.
*/
@Override
@Nullable
public Integer getPriority(Object obj) {
public @Nullable Integer getPriority(Object obj) {
if (obj instanceof Class<?> clazz) {
return OrderUtils.getPriority(clazz);
}

View File

@@ -33,9 +33,9 @@ import java.util.function.Predicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotationTypeMapping.MirrorSets.MirrorSet;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -72,8 +72,7 @@ final class AnnotationTypeMapping {
private static final int[] EMPTY_INT_ARRAY = new int[0];
@Nullable
private final AnnotationTypeMapping source;
private final @Nullable AnnotationTypeMapping source;
private final AnnotationTypeMapping root;
@@ -83,8 +82,7 @@ final class AnnotationTypeMapping {
private final List<Class<? extends Annotation>> metaTypes;
@Nullable
private final Annotation annotation;
private final @Nullable Annotation annotation;
private final AttributeMethods attributes;
@@ -481,8 +479,7 @@ final class AnnotationTypeMapping {
* Get the source of the mapping or {@code null}.
* @return the source of the mapping
*/
@Nullable
AnnotationTypeMapping getSource() {
@Nullable AnnotationTypeMapping getSource() {
return this.source;
}
@@ -511,8 +508,7 @@ final class AnnotationTypeMapping {
* meta-annotation, or {@code null} if this is the root mapping.
* @return the source annotation of the mapping
*/
@Nullable
Annotation getAnnotation() {
@Nullable Annotation getAnnotation() {
return this.annotation;
}
@@ -560,8 +556,7 @@ final class AnnotationTypeMapping {
* also be considered.
* @return the mapped annotation value, or {@code null}
*/
@Nullable
Object getMappedAnnotationValue(int attributeIndex, boolean metaAnnotationsOnly) {
@Nullable Object getMappedAnnotationValue(int attributeIndex, boolean metaAnnotationsOnly) {
int mappedIndex = this.annotationValueMappings[attributeIndex];
if (mappedIndex == -1) {
return null;
@@ -727,8 +722,7 @@ final class AnnotationTypeMapping {
return this.mirrorSets[index];
}
@Nullable
MirrorSet getAssigned(int attributeIndex) {
@Nullable MirrorSet getAssigned(int attributeIndex) {
return this.assigned[attributeIndex];
}

View File

@@ -25,7 +25,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ConcurrentReferenceHashMap;
/**

View File

@@ -30,11 +30,12 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.annotation.AnnotationTypeMapping.MirrorSets.MirrorSet;
import org.springframework.core.annotation.MergedAnnotation.Adapt;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
@@ -187,8 +188,7 @@ public abstract class AnnotationUtils {
* @since 4.0
*/
@SuppressWarnings("unchecked")
@Nullable
public static <A extends Annotation> A getAnnotation(Annotation annotation, Class<A> annotationType) {
public static <A extends Annotation> @Nullable A getAnnotation(Annotation annotation, Class<A> annotationType) {
// Shortcut: directly present on the element, with no merging needed?
if (annotationType.isInstance(annotation)) {
return synthesizeAnnotation((A) annotation, annotationType);
@@ -215,8 +215,7 @@ public abstract class AnnotationUtils {
* @return the first matching annotation, or {@code null} if not found
* @since 3.1
*/
@Nullable
public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
public static <A extends Annotation> @Nullable A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
// Shortcut: directly present on the element, with no merging needed?
if (AnnotationFilter.PLAIN.matches(annotationType) ||
AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotatedElement)) {
@@ -247,8 +246,7 @@ public abstract class AnnotationUtils {
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
* @see #getAnnotation(AnnotatedElement, Class)
*/
@Nullable
public static <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) {
public static <A extends Annotation> @Nullable A getAnnotation(Method method, Class<A> annotationType) {
Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
return getAnnotation((AnnotatedElement) resolvedMethod, annotationType);
}
@@ -266,8 +264,7 @@ public abstract class AnnotationUtils {
* @deprecated as of 5.2 since it is superseded by the {@link MergedAnnotations} API
*/
@Deprecated
@Nullable
public static Annotation[] getAnnotations(AnnotatedElement annotatedElement) {
public static Annotation @Nullable [] getAnnotations(AnnotatedElement annotatedElement) {
try {
return synthesizeAnnotationArray(annotatedElement.getAnnotations(), annotatedElement);
}
@@ -291,8 +288,7 @@ public abstract class AnnotationUtils {
* @deprecated as of 5.2 since it is superseded by the {@link MergedAnnotations} API
*/
@Deprecated
@Nullable
public static Annotation[] getAnnotations(Method method) {
public static Annotation @Nullable [] getAnnotations(Method method) {
try {
return synthesizeAnnotationArray(BridgeMethodResolver.findBridgedMethod(method).getAnnotations(), method);
}
@@ -480,8 +476,7 @@ public abstract class AnnotationUtils {
* @return the first matching annotation, or {@code null} if not found
* @since 4.2
*/
@Nullable
public static <A extends Annotation> A findAnnotation(
public static <A extends Annotation> @Nullable A findAnnotation(
AnnotatedElement annotatedElement, @Nullable Class<A> annotationType) {
if (annotationType == null) {
@@ -515,8 +510,7 @@ public abstract class AnnotationUtils {
* @return the first matching annotation, or {@code null} if not found
* @see #getAnnotation(Method, Class)
*/
@Nullable
public static <A extends Annotation> A findAnnotation(Method method, @Nullable Class<A> annotationType) {
public static <A extends Annotation> @Nullable A findAnnotation(Method method, @Nullable Class<A> annotationType) {
if (annotationType == null) {
return null;
}
@@ -555,8 +549,7 @@ public abstract class AnnotationUtils {
* @param annotationType the type of annotation to look for
* @return the first matching annotation, or {@code null} if not found
*/
@Nullable
public static <A extends Annotation> A findAnnotation(Class<?> clazz, @Nullable Class<A> annotationType) {
public static <A extends Annotation> @Nullable A findAnnotation(Class<?> clazz, @Nullable Class<A> annotationType) {
if (annotationType == null) {
return null;
}
@@ -605,8 +598,7 @@ public abstract class AnnotationUtils {
* @deprecated as of 5.2 since it is superseded by the {@link MergedAnnotations} API
*/
@Deprecated
@Nullable
public static Class<?> findAnnotationDeclaringClass(
public static @Nullable Class<?> findAnnotationDeclaringClass(
Class<? extends Annotation> annotationType, @Nullable Class<?> clazz) {
if (clazz == null) {
@@ -642,8 +634,7 @@ public abstract class AnnotationUtils {
* @deprecated as of 5.2 since it is superseded by the {@link MergedAnnotations} API
*/
@Deprecated
@Nullable
public static Class<?> findAnnotationDeclaringClassForTypes(
public static @Nullable Class<?> findAnnotationDeclaringClassForTypes(
List<Class<? extends Annotation>> annotationTypes, @Nullable Class<?> clazz) {
if (clazz == null) {
@@ -984,8 +975,7 @@ public abstract class AnnotationUtils {
}
}
@Nullable
private static Object getAttributeValueForMirrorResolution(Method attribute, @Nullable Object attributes) {
private static @Nullable Object getAttributeValueForMirrorResolution(Method attribute, @Nullable Object attributes) {
if (!(attributes instanceof AnnotationAttributes annotationAttributes)) {
return null;
}
@@ -993,8 +983,7 @@ public abstract class AnnotationUtils {
return (result instanceof DefaultValueHolder defaultValueHolder ? defaultValueHolder.defaultValue : result);
}
@Nullable
private static Object adaptValue(
private static @Nullable Object adaptValue(
@Nullable Object annotatedElement, @Nullable Object value, boolean classValuesAsString) {
if (classValuesAsString) {
@@ -1032,8 +1021,7 @@ public abstract class AnnotationUtils {
* in which case such an exception will be rethrown
* @see #getValue(Annotation, String)
*/
@Nullable
public static Object getValue(Annotation annotation) {
public static @Nullable Object getValue(Annotation annotation) {
return getValue(annotation, VALUE);
}
@@ -1046,8 +1034,7 @@ public abstract class AnnotationUtils {
* in which case such an exception will be rethrown
* @see #getValue(Annotation)
*/
@Nullable
public static Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) {
public static @Nullable Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) {
if (annotation == null || !StringUtils.hasText(attributeName)) {
return null;
}
@@ -1075,8 +1062,7 @@ public abstract class AnnotationUtils {
* @return the value returned from the method invocation
* @since 5.3.24
*/
@Nullable
static Object invokeAnnotationMethod(Method method, @Nullable Object annotation) {
static @Nullable Object invokeAnnotationMethod(Method method, @Nullable Object annotation) {
if (annotation == null) {
return null;
}
@@ -1156,8 +1142,7 @@ public abstract class AnnotationUtils {
* @return the default value, or {@code null} if not found
* @see #getDefaultValue(Annotation, String)
*/
@Nullable
public static Object getDefaultValue(Annotation annotation) {
public static @Nullable Object getDefaultValue(Annotation annotation) {
return getDefaultValue(annotation, VALUE);
}
@@ -1168,8 +1153,7 @@ public abstract class AnnotationUtils {
* @return the default value of the named attribute, or {@code null} if not found
* @see #getDefaultValue(Class, String)
*/
@Nullable
public static Object getDefaultValue(@Nullable Annotation annotation, @Nullable String attributeName) {
public static @Nullable Object getDefaultValue(@Nullable Annotation annotation, @Nullable String attributeName) {
return (annotation != null ? getDefaultValue(annotation.annotationType(), attributeName) : null);
}
@@ -1180,8 +1164,7 @@ public abstract class AnnotationUtils {
* @return the default value, or {@code null} if not found
* @see #getDefaultValue(Class, String)
*/
@Nullable
public static Object getDefaultValue(Class<? extends Annotation> annotationType) {
public static @Nullable Object getDefaultValue(Class<? extends Annotation> annotationType) {
return getDefaultValue(annotationType, VALUE);
}
@@ -1193,8 +1176,7 @@ public abstract class AnnotationUtils {
* @return the default value of the named attribute, or {@code null} if not found
* @see #getDefaultValue(Annotation, String)
*/
@Nullable
public static Object getDefaultValue(
public static @Nullable Object getDefaultValue(
@Nullable Class<? extends Annotation> annotationType, @Nullable String attributeName) {
if (annotationType == null || !StringUtils.hasText(attributeName)) {

View File

@@ -18,7 +18,7 @@ package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Callback interface used to process annotations.
@@ -40,8 +40,7 @@ interface AnnotationsProcessor<C, R> {
* @param aggregateIndex the aggregate index about to be processed
* @return a {@code non-null} result if no further processing is required
*/
@Nullable
default R doWithAggregate(C context, int aggregateIndex) {
default @Nullable R doWithAggregate(C context, int aggregateIndex) {
return null;
}
@@ -55,8 +54,7 @@ interface AnnotationsProcessor<C, R> {
* {@code null} elements)
* @return a {@code non-null} result if no further processing is required
*/
@Nullable
R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source, Annotation[] annotations);
@Nullable R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source, Annotation[] annotations);
/**
* Get the final result to be returned. By default this method returns
@@ -64,8 +62,7 @@ interface AnnotationsProcessor<C, R> {
* @param result the last early exit result, or {@code null} if none
* @return the final result to be returned to the caller
*/
@Nullable
default R finish(@Nullable R result) {
default @Nullable R finish(@Nullable R result) {
return result;
}

View File

@@ -25,12 +25,13 @@ import java.util.Arrays;
import java.util.Map;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotations.Search;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Nullable;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -75,16 +76,14 @@ abstract class AnnotationsScanner {
* @param processor the processor that receives the annotations
* @return the result of {@link AnnotationsProcessor#finish(Object)}
*/
@Nullable
static <C, R> R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy,
static <C, R> @Nullable R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy,
Predicate<Class<?>> searchEnclosingClass, AnnotationsProcessor<C, R> processor) {
R result = process(context, source, searchStrategy, searchEnclosingClass, processor);
return processor.finish(result);
}
@Nullable
private static <C, R> R process(C context, AnnotatedElement source,
private static <C, R> @Nullable R process(C context, AnnotatedElement source,
SearchStrategy searchStrategy, Predicate<Class<?>> searchEnclosingClass,
AnnotationsProcessor<C, R> processor) {
@@ -97,8 +96,7 @@ abstract class AnnotationsScanner {
return processElement(context, source, processor);
}
@Nullable
private static <C, R> R processClass(C context, Class<?> source, SearchStrategy searchStrategy,
private static <C, R> @Nullable R processClass(C context, Class<?> source, SearchStrategy searchStrategy,
Predicate<Class<?>> searchEnclosingClass, AnnotationsProcessor<C, R> processor) {
return switch (searchStrategy) {
@@ -109,8 +107,7 @@ abstract class AnnotationsScanner {
};
}
@Nullable
private static <C, R> R processClassInheritedAnnotations(C context, Class<?> source,
private static <C, R> @Nullable R processClassInheritedAnnotations(C context, Class<?> source,
AnnotationsProcessor<C, R> processor) {
try {
@@ -164,8 +161,7 @@ abstract class AnnotationsScanner {
return null;
}
@Nullable
private static <C, R> R processClassHierarchy(C context, Class<?> source,
private static <C, R> @Nullable R processClassHierarchy(C context, Class<?> source,
AnnotationsProcessor<C, R> processor, boolean includeInterfaces,
Predicate<Class<?>> searchEnclosingClass) {
@@ -173,8 +169,7 @@ abstract class AnnotationsScanner {
includeInterfaces, searchEnclosingClass);
}
@Nullable
private static <C, R> R processClassHierarchy(C context, int[] aggregateIndex, Class<?> source,
private static <C, R> @Nullable R processClassHierarchy(C context, int[] aggregateIndex, Class<?> source,
AnnotationsProcessor<C, R> processor, boolean includeInterfaces,
Predicate<Class<?>> searchEnclosingClass) {
@@ -236,8 +231,7 @@ abstract class AnnotationsScanner {
return null;
}
@Nullable
private static <C, R> R processMethod(C context, Method source,
private static <C, R> @Nullable R processMethod(C context, Method source,
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {
return switch (searchStrategy) {
@@ -249,8 +243,7 @@ abstract class AnnotationsScanner {
};
}
@Nullable
private static <C, R> R processMethodInheritedAnnotations(C context, Method source,
private static <C, R> @Nullable R processMethodInheritedAnnotations(C context, Method source,
AnnotationsProcessor<C, R> processor) {
try {
@@ -264,8 +257,7 @@ abstract class AnnotationsScanner {
return null;
}
@Nullable
private static <C, R> R processMethodHierarchy(C context, int[] aggregateIndex,
private static <C, R> @Nullable R processMethodHierarchy(C context, int[] aggregateIndex,
Class<?> sourceClass, AnnotationsProcessor<C, R> processor, Method rootMethod,
boolean includeInterfaces) {
@@ -390,8 +382,7 @@ abstract class AnnotationsScanner {
return true;
}
@Nullable
private static <C, R> R processMethodAnnotations(C context, int aggregateIndex, Method source,
private static <C, R> @Nullable R processMethodAnnotations(C context, int aggregateIndex, Method source,
AnnotationsProcessor<C, R> processor) {
Annotation[] annotations = getDeclaredAnnotations(source, false);
@@ -412,8 +403,7 @@ abstract class AnnotationsScanner {
return null;
}
@Nullable
private static <C, R> R processElement(C context, AnnotatedElement source,
private static <C, R> @Nullable R processElement(C context, AnnotatedElement source,
AnnotationsProcessor<C, R> processor) {
try {
@@ -428,8 +418,7 @@ abstract class AnnotationsScanner {
}
@SuppressWarnings("unchecked")
@Nullable
static <A extends Annotation> A getDeclaredAnnotation(AnnotatedElement source, Class<A> annotationType) {
static <A extends Annotation> @Nullable A getDeclaredAnnotation(AnnotatedElement source, Class<A> annotationType) {
Annotation[] annotations = getDeclaredAnnotations(source, false);
for (Annotation annotation : annotations) {
if (annotation != null && annotationType == annotation.annotationType()) {

View File

@@ -22,7 +22,8 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
@@ -49,8 +50,7 @@ final class AttributeMethods {
};
@Nullable
private final Class<? extends Annotation> annotationType;
private final @Nullable Class<? extends Annotation> annotationType;
private final Method[] attributeMethods;
@@ -155,8 +155,7 @@ final class AttributeMethods {
* @param name the attribute name to find
* @return the attribute method or {@code null}
*/
@Nullable
Method get(String name) {
@Nullable Method get(String name) {
int index = indexOf(name);
return (index != -1 ? this.attributeMethods[index] : null);
}

View File

@@ -18,8 +18,7 @@ package org.springframework.core.annotation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Log facade used to handle annotation introspection failures (in particular
@@ -55,8 +54,7 @@ enum IntrospectionFailureLogger {
};
@Nullable
private static Log logger;
private static @Nullable Log logger;
void log(String message, @Nullable Object source, Exception ex) {

View File

@@ -28,8 +28,9 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Nullable;
/**
* A single merged annotation returned from a {@link MergedAnnotations}
@@ -133,8 +134,7 @@ public interface MergedAnnotation<A extends Annotation> {
* {@link #getRoot() root}.
* @return the source, or {@code null}
*/
@Nullable
Object getSource();
@Nullable Object getSource();
/**
* Get the source of the meta-annotation, or {@code null} if the
@@ -144,8 +144,7 @@ public interface MergedAnnotation<A extends Annotation> {
* @return the meta-annotation source or {@code null}
* @see #getRoot()
*/
@Nullable
MergedAnnotation<?> getMetaSource();
@Nullable MergedAnnotation<?> getMetaSource();
/**
* Get the root annotation, i.e. the {@link #getDistance() distance} {@code 0}

View File

@@ -23,7 +23,8 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -125,8 +126,7 @@ public abstract class MergedAnnotationPredicates {
private boolean hasLastValue;
@Nullable
private Object lastValue;
private @Nullable Object lastValue;
FirstRunOfPredicate(Function<? super MergedAnnotation<A>, ?> valueExtractor) {
Assert.notNull(valueExtractor, "Value extractor must not be null");

View File

@@ -24,7 +24,8 @@ import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -26,7 +26,8 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@@ -155,8 +156,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
}
@SuppressWarnings("unchecked")
@Nullable
private <A extends Annotation> MergedAnnotation<A> find(Object requiredType,
private <A extends Annotation> @Nullable MergedAnnotation<A> find(Object requiredType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector) {
@@ -222,8 +222,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
private class AnnotationsSpliterator<A extends Annotation> implements Spliterator<MergedAnnotation<A>> {
@Nullable
private final Object requiredType;
private final @Nullable Object requiredType;
private final int[] mappingCursors;
@@ -259,8 +258,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
return false;
}
@Nullable
private AnnotationTypeMapping getNextSuitableMapping(int annotationIndex) {
private @Nullable AnnotationTypeMapping getNextSuitableMapping(int annotationIndex) {
AnnotationTypeMapping mapping;
do {
mapping = getMapping(annotationIndex, this.mappingCursors[annotationIndex]);
@@ -273,15 +271,13 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
return null;
}
@Nullable
private AnnotationTypeMapping getMapping(int annotationIndex, int mappingIndex) {
private @Nullable AnnotationTypeMapping getMapping(int annotationIndex, int mappingIndex) {
AnnotationTypeMappings mappings = MergedAnnotationsCollection.this.mappings[annotationIndex];
return (mappingIndex < mappings.size() ? mappings.get(mappingIndex) : null);
}
@Nullable
@SuppressWarnings("unchecked")
private MergedAnnotation<A> createMergedAnnotationIfPossible(int annotationIndex, int mappingIndex) {
private @Nullable MergedAnnotation<A> createMergedAnnotationIfPossible(int annotationIndex, int mappingIndex) {
MergedAnnotation<?> root = annotations[annotationIndex];
if (mappingIndex == 0) {
return (MergedAnnotation<A>) root;
@@ -293,8 +289,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
}
@Override
@Nullable
public Spliterator<MergedAnnotation<A>> trySplit() {
public @Nullable Spliterator<MergedAnnotation<A>> trySplit() {
return null;
}

Some files were not shown because too many files have changed in this diff Show More