Introduce null-safety of Spring Framework API

This commit introduces 2 new @Nullable and @NonNullApi
annotations that leverage JSR 305 (dormant but available via
Findbugs jsr305 dependency and already used by libraries
like OkHttp) meta-annotations to specify explicitly
null-safety of Spring Framework parameters and return values.

In order to avoid adding too much annotations, the
default is set at package level with @NonNullApi and
@Nullable annotations are added when needed at parameter or
return value level. These annotations are intended to be used
on Spring Framework itself but also by other Spring projects.

@Nullable annotations have been introduced based on Javadoc
and search of patterns like "return null;". It is expected that
nullability of Spring Framework API will be polished with
complementary commits.

In practice, this will make the whole Spring Framework API
null-safe for Kotlin projects (when KT-10942 will be fixed)
since Kotlin will be able to leverage these annotations to
know if a parameter or a return value is nullable or not. But
this is also useful for Java developers as well since IntelliJ
IDEA, for example, also understands these annotations to
generate warnings when unsafe nullable usages are detected.

Issue: SPR-15540
This commit is contained in:
Sebastien Deleuze
2017-05-27 08:14:59 +02:00
parent 2d37c966b2
commit 87598f48e4
1315 changed files with 4831 additions and 963 deletions

View File

@@ -16,6 +16,8 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
/**
* Interface defining a generic contract for attaching and accessing metadata
* to/from arbitrary objects.
@@ -34,7 +36,7 @@ public interface AttributeAccessor {
* @param name the unique attribute key
* @param value the attribute value to be attached
*/
void setAttribute(String name, Object value);
void setAttribute(String name, @Nullable Object value);
/**
* Get the value of the attribute identified by {@code name}.
@@ -42,6 +44,7 @@ public interface AttributeAccessor {
* @param name the unique attribute key
* @return the current value of the attribute, if any
*/
@Nullable
Object getAttribute(String name);
/**
@@ -50,6 +53,7 @@ public interface AttributeAccessor {
* @param name the unique attribute key
* @return the last value of the attribute, if any
*/
@Nullable
Object removeAttribute(String name);
/**

View File

@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -102,7 +103,8 @@ public abstract class BridgeMethodResolver {
* @param bridgeMethod the bridge method
* @return the bridged method, or {@code null} if none found
*/
private static Method searchCandidates(List<Method> candidateMethods, Method bridgeMethod) {
@Nullable
private static Method searchCandidates(@Nullable List<Method> candidateMethods, Method bridgeMethod) {
if (candidateMethods.isEmpty()) {
return null;
}
@@ -138,6 +140,7 @@ public abstract 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) {
// Search parent types for method that has same signature as bridge.
Class<?> superclass = bridgeMethod.getDeclaringClass().getSuperclass();
@@ -196,6 +199,7 @@ public abstract 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) {
return ReflectionUtils.findMethod(type, bridgeMethod.getName(), bridgeMethod.getParameterTypes());
}

View File

@@ -36,6 +36,7 @@ import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -115,7 +116,7 @@ public abstract class CollectionFactory {
* @see java.util.LinkedHashSet
*/
@SuppressWarnings({ "unchecked", "cast", "rawtypes" })
public static <E> Collection<E> createApproximateCollection(Object collection, int capacity) {
public static <E> Collection<E> createApproximateCollection(@Nullable Object collection, int capacity) {
if (collection instanceof LinkedList) {
return new LinkedList<>();
}
@@ -174,7 +175,7 @@ public abstract class CollectionFactory {
* the supplied {@code elementType} is not a subtype of {@link Enum}
*/
@SuppressWarnings({ "unchecked", "cast" })
public static <E> Collection<E> createCollection(Class<?> collectionType, Class<?> elementType, int capacity) {
public static <E> Collection<E> createCollection(Class<?> collectionType, @Nullable Class<?> elementType, int capacity) {
Assert.notNull(collectionType, "Collection type must not be null");
if (collectionType.isInterface()) {
if (Set.class == collectionType || Collection.class == collectionType) {
@@ -237,7 +238,7 @@ public abstract class CollectionFactory {
* @see java.util.LinkedHashMap
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static <K, V> Map<K, V> createApproximateMap(Object map, int capacity) {
public static <K, V> Map<K, V> createApproximateMap(@Nullable Object map, int capacity) {
if (map instanceof EnumMap) {
EnumMap enumMap = new EnumMap((EnumMap) map);
enumMap.clear();
@@ -290,7 +291,7 @@ public abstract class CollectionFactory {
* the supplied {@code keyType} is not a subtype of {@link Enum}
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static <K, V> Map<K, V> createMap(Class<?> mapType, Class<?> keyType, int capacity) {
public static <K, V> Map<K, V> createMap(Class<?> mapType, @Nullable Class<?> keyType, int capacity) {
Assert.notNull(mapType, "Map type must not be null");
if (mapType.isInterface()) {
if (Map.class == mapType) {

View File

@@ -22,6 +22,7 @@ import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -142,6 +143,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 {
return null;
}

View File

@@ -23,6 +23,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -157,7 +158,7 @@ public class Constants {
* @param namePrefix prefix of the constant names to search (may be {@code null})
* @return the set of constant names
*/
public Set<String> getNames(String namePrefix) {
public Set<String> getNames(@Nullable String namePrefix) {
String prefixToUse = (namePrefix != null ? namePrefix.trim().toUpperCase(Locale.ENGLISH) : "");
Set<String> names = new HashSet<>();
for (String code : this.fieldCache.keySet()) {
@@ -189,7 +190,7 @@ public class Constants {
* @param nameSuffix suffix of the constant names to search (may be {@code null})
* @return the set of constant names
*/
public Set<String> getNamesForSuffix(String nameSuffix) {
public Set<String> getNamesForSuffix(@Nullable String nameSuffix) {
String suffixToUse = (nameSuffix != null ? nameSuffix.trim().toUpperCase(Locale.ENGLISH) : "");
Set<String> names = new HashSet<>();
for (String code : this.fieldCache.keySet()) {
@@ -211,7 +212,7 @@ public class Constants {
* @param namePrefix prefix of the constant names to search (may be {@code null})
* @return the set of values
*/
public Set<Object> getValues(String namePrefix) {
public Set<Object> getValues(@Nullable String namePrefix) {
String prefixToUse = (namePrefix != null ? namePrefix.trim().toUpperCase(Locale.ENGLISH) : "");
Set<Object> values = new HashSet<>();
for (String code : this.fieldCache.keySet()) {
@@ -243,7 +244,7 @@ public class Constants {
* @param nameSuffix suffix of the constant names to search (may be {@code null})
* @return the set of values
*/
public Set<Object> getValuesForSuffix(String nameSuffix) {
public Set<Object> getValuesForSuffix(@Nullable String nameSuffix) {
String suffixToUse = (nameSuffix != null ? nameSuffix.trim().toUpperCase(Locale.ENGLISH) : "");
Set<Object> values = new HashSet<>();
for (String code : this.fieldCache.keySet()) {
@@ -263,7 +264,7 @@ public class Constants {
* @return the name of the constant field
* @throws ConstantException if the value wasn't found
*/
public String toCode(Object value, String namePrefix) throws ConstantException {
public String toCode(Object value, @Nullable String namePrefix) throws ConstantException {
String prefixToUse = (namePrefix != null ? namePrefix.trim().toUpperCase(Locale.ENGLISH) : "");
for (Map.Entry<String, Object> entry : this.fieldCache.entrySet()) {
if (entry.getKey().startsWith(prefixToUse) && entry.getValue().equals(value)) {
@@ -294,7 +295,7 @@ public class Constants {
* @return the name of the constant field
* @throws ConstantException if the value wasn't found
*/
public String toCodeForSuffix(Object value, String nameSuffix) throws ConstantException {
public String toCodeForSuffix(Object value, @Nullable String nameSuffix) throws ConstantException {
String suffixToUse = (nameSuffix != null ? nameSuffix.trim().toUpperCase(Locale.ENGLISH) : "");
for (Map.Entry<String, Object> entry : this.fieldCache.entrySet()) {
if (entry.getKey().endsWith(suffixToUse) && entry.getValue().equals(value)) {

View File

@@ -27,6 +27,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -171,7 +172,7 @@ public abstract class Conventions {
* @param value the return value (may be {@code null} if not available)
* @return the generated variable name
*/
public static String getVariableNameForReturnType(Method method, Object value) {
public static String getVariableNameForReturnType(Method method, @Nullable Object value) {
return getVariableNameForReturnType(method, method.getReturnType(), value);
}
@@ -191,7 +192,7 @@ public abstract class Conventions {
* @param value the return value (may be {@code null} if not available)
* @return the generated variable name
*/
public static String getVariableNameForReturnType(Method method, Class<?> resolvedType, Object value) {
public static String getVariableNameForReturnType(Method method, Class<?> resolvedType, @Nullable Object value) {
Assert.notNull(method, "Method must not be null");
if (Object.class == resolvedType) {

View File

@@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
@@ -83,6 +84,7 @@ public abstract 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<?> genericIfc) {
Assert.notNull(method, "method must not be null");
ResolvableType resolvableType = ResolvableType.forMethodReturnType(method).as(genericIfc);
@@ -100,6 +102,7 @@ public abstract class GenericTypeResolver {
* @param genericIfc 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<?> genericIfc) {
ResolvableType resolvableType = ResolvableType.forClass(clazz).as(genericIfc);
if (!resolvableType.hasGenerics()) {
@@ -125,6 +128,7 @@ public abstract 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<?> genericIfc) {
ResolvableType type = ResolvableType.forClass(clazz).as(genericIfc);
if (!type.hasGenerics() || type.isEntirelyUnresolvable()) {
@@ -142,6 +146,7 @@ public abstract class GenericTypeResolver {
* @return the resolved type (possibly the given generic type as-is)
* @since 5.0
*/
@Nullable
public static Type resolveType(Type genericType, Class<?> contextClass) {
if (contextClass != null) {
if (genericType instanceof TypeVariable) {

View File

@@ -18,6 +18,7 @@ package org.springframework.core;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -41,7 +42,7 @@ public final class MethodClassKey implements Comparable<MethodClassKey> {
* @param targetClass the target class that the method will be invoked
* on (may be {@code null} if identical to the declaring class)
*/
public MethodClassKey(Method method, Class<?> targetClass) {
public MethodClassKey(Method method, @Nullable Class<?> targetClass) {
this.method = method;
this.targetClass = targetClass;
}

View File

@@ -24,6 +24,7 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -51,7 +52,7 @@ public abstract class MethodIntrospector {
* @return the selected methods associated with their metadata (in the order of retrieval),
* or an empty map in case of no match
*/
public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {
public static <T> Map<Method, T> selectMethods(Class<?> targetType, @Nullable final MetadataLookup<T> metadataLookup) {
final Map<Method, T> methodMap = new LinkedHashMap<>();
Set<Class<?>> handlerTypes = new LinkedHashSet<>();
Class<?> specificHandlerType = null;
@@ -155,6 +156,7 @@ public abstract 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);
}

View File

@@ -36,6 +36,7 @@ import kotlin.reflect.KFunction;
import kotlin.reflect.KParameter;
import kotlin.reflect.jvm.ReflectJvmMapping;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -171,6 +172,7 @@ public class MethodParameter {
* <p>Note: Either Method or Constructor is available.
* @return the Method, or {@code null} if none
*/
@Nullable
public Method getMethod() {
return this.method;
}
@@ -180,6 +182,7 @@ public class MethodParameter {
* <p>Note: Either Method or Constructor is available.
* @return the Constructor, or {@code null} if none
*/
@Nullable
public Constructor<?> getConstructor() {
return this.constructor;
}
@@ -279,6 +282,7 @@ public class MethodParameter {
* if none specified (indicating the default type index)
* @see #getNestingLevel()
*/
@Nullable
public Integer getTypeIndexForCurrentLevel() {
return getTypeIndexForLevel(this.nestingLevel);
}
@@ -289,6 +293,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) {
return getTypeIndexesPerLevel().get(nestingLevel);
}
@@ -482,6 +487,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) {
return adaptAnnotation(getAnnotatedElement().getAnnotation(annotationType));
}
@@ -528,6 +534,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) {
Annotation[] anns = getParameterAnnotations();
for (Annotation ann : anns) {
@@ -564,6 +571,7 @@ public class MethodParameter {
* {@link #initParameterNameDiscovery ParameterNameDiscoverer}
* has been set to begin with)
*/
@Nullable
public String getParameterName() {
ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
if (discoverer != null) {

View File

@@ -16,6 +16,8 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
/**
* Handy class for wrapping checked {@code Exceptions} with a root cause.
*
@@ -79,6 +81,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() {
return NestedExceptionUtils.getRootCause(this);
}

View File

@@ -16,6 +16,8 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
/**
* Helper class for implementing exception classes which are capable of
* holding nested exceptions. Necessary because we can't share a base
@@ -56,6 +58,7 @@ public abstract class NestedExceptionUtils {
* @return the innermost exception, or {@code null} if none
* @since 4.3.9
*/
@Nullable
public static Throwable getRootCause(Throwable original) {
if (original == null) {
return null;

View File

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

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -135,6 +136,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) {
return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}
@@ -150,6 +152,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) {
return null;
}
@@ -215,6 +218,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);
}

View File

@@ -19,6 +19,7 @@ package org.springframework.core;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;
/**
@@ -113,6 +114,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 {
Class<?> result = findLoadedClass(name);
if (result == null) {
@@ -134,6 +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 {
InputStream is = openStreamForClass(name);
if (is == null) {

View File

@@ -19,6 +19,8 @@ package org.springframework.core;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* Interface to discover parameter names for methods and constructors.
*
@@ -40,6 +42,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);
/**
@@ -49,6 +52,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(Constructor<?> ctor);
}

View File

@@ -28,6 +28,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import rx.RxReactiveStreams;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -120,7 +121,8 @@ public class ReactiveAdapterRegistry {
* @param source an instance of the reactive type
* (i.e. to adapt from; may be {@code null} if the reactive type is specified)
*/
public ReactiveAdapter getAdapter(Class<?> reactiveType, Object source) {
@Nullable
public ReactiveAdapter getAdapter(@Nullable Class<?> reactiveType, Object source) {
Object sourceToUse = (source instanceof Optional ? ((Optional<?>) source).orElse(null) : source);
Class<?> clazz = (sourceToUse != null ? sourceToUse.getClass() : reactiveType);

View File

@@ -34,6 +34,7 @@ import java.util.Map;
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;
@@ -196,6 +197,7 @@ public class ResolvableType implements Serializable {
* Return the underlying Java {@link Class} being managed, if available;
* otherwise {@code null}.
*/
@Nullable
public Class<?> getRawClass() {
if (this.type == this.resolved) {
return this.resolved;
@@ -587,7 +589,7 @@ public class ResolvableType implements Serializable {
* level (may be {@code null})
* @return a {@link ResolvableType} for the nested level or {@link #NONE}
*/
public ResolvableType getNested(int nestingLevel, Map<Integer, Integer> typeIndexesPerLevel) {
public ResolvableType getNested(int nestingLevel, @Nullable Map<Integer, Integer> typeIndexesPerLevel) {
ResolvableType result = this;
for (int i = 2; i <= nestingLevel; i++) {
if (result.isArray()) {
@@ -716,6 +718,7 @@ public class ResolvableType implements Serializable {
* @see #getGeneric(int...)
* @see #resolve()
*/
@Nullable
public Class<?> resolveGeneric(int... indexes) {
return getGeneric(indexes).resolve();
}
@@ -730,6 +733,7 @@ public class ResolvableType implements Serializable {
* @see #resolveGeneric(int...)
* @see #resolveGenerics()
*/
@Nullable
public Class<?> resolve() {
return resolve(null);
}
@@ -745,7 +749,7 @@ public class ResolvableType implements Serializable {
* @see #resolveGeneric(int...)
* @see #resolveGenerics()
*/
public Class<?> resolve(Class<?> fallback) {
public Class<?> resolve(@Nullable Class<?> fallback) {
return (this.resolved != null ? this.resolved : fallback);
}
@@ -791,6 +795,7 @@ public class ResolvableType implements Serializable {
return NONE;
}
@Nullable
private Type resolveBounds(Type[] bounds) {
if (ObjectUtils.isEmpty(bounds) || Object.class == bounds[0]) {
return null;
@@ -798,6 +803,7 @@ public class ResolvableType implements Serializable {
return bounds[0];
}
@Nullable
private ResolvableType resolveVariable(TypeVariable<?> variable) {
if (this.type instanceof TypeVariable) {
return resolveType().resolveVariable(variable);
@@ -873,6 +879,7 @@ public class ResolvableType implements Serializable {
/**
* Adapts this {@link ResolvableType} to a {@link VariableResolver}.
*/
@Nullable
VariableResolver asVariableResolver() {
if (this == NONE) {
return null;
@@ -929,7 +936,7 @@ public class ResolvableType implements Serializable {
* @see #forClass(Class, Class)
* @see #forClassWithGenerics(Class, Class...)
*/
public static ResolvableType forClass(Class<?> clazz) {
public static ResolvableType forClass(@Nullable Class<?> clazz) {
return new ResolvableType(clazz);
}
@@ -945,7 +952,7 @@ public class ResolvableType implements Serializable {
* @see #forClass(Class)
* @see #getRawClass()
*/
public static ResolvableType forRawClass(Class<?> clazz) {
public static ResolvableType forRawClass(@Nullable Class<?> clazz) {
return new ResolvableType(clazz) {
@Override
public ResolvableType[] getGenerics() {
@@ -1289,7 +1296,7 @@ public class ResolvableType implements Serializable {
* @return a {@link ResolvableType} for the specified {@link Type}
* @see #forType(Type, ResolvableType)
*/
public static ResolvableType forType(Type type) {
public static ResolvableType forType(@Nullable Type type) {
return forType(type, null, null);
}
@@ -1301,7 +1308,7 @@ public class ResolvableType implements Serializable {
* @return a {@link ResolvableType} for the specified {@link Type} and owner
* @see #forType(Type)
*/
public static ResolvableType forType(Type type, ResolvableType owner) {
public static ResolvableType forType(@Nullable Type type, ResolvableType owner) {
VariableResolver variableResolver = null;
if (owner != null) {
variableResolver = owner.asVariableResolver();
@@ -1316,7 +1323,7 @@ public class ResolvableType implements Serializable {
* @param variableResolver the variable resolver or {@code null}
* @return a {@link ResolvableType} for the specified {@link Type} and {@link VariableResolver}
*/
static ResolvableType forType(Type type, VariableResolver variableResolver) {
static ResolvableType forType(@Nullable Type type, @Nullable VariableResolver variableResolver) {
return forType(type, null, variableResolver);
}
@@ -1328,7 +1335,7 @@ public class ResolvableType implements Serializable {
* @param variableResolver the variable resolver or {@code null}
* @return a {@link ResolvableType} for the specified {@link Type} and {@link VariableResolver}
*/
static ResolvableType forType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) {
static ResolvableType forType(@Nullable Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver) {
if (type == null && typeProvider != null) {
type = SerializableTypeWrapper.forTypeProvider(typeProvider);
}
@@ -1380,6 +1387,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);
}
@@ -1535,6 +1543,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) {
ResolvableType resolveToWildcard = type;
while (!(resolveToWildcard.getType() instanceof WildcardType)) {

View File

@@ -16,6 +16,8 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
/**
* Any object can implement this interface to provide its actual {@link ResolvableType}.
*
@@ -35,6 +37,7 @@ 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();
}

View File

@@ -30,6 +30,7 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
@@ -179,6 +180,7 @@ abstract class SerializableTypeWrapper {
* Return the source of the type, or {@code null} if not known.
* <p>The default implementations returns {@code null}.
*/
@Nullable
default Object getSource() {
return null;
}

View File

@@ -24,6 +24,8 @@ import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
/**
* Static holder for local Spring properties, i.e. defined at the Spring library level.
*
@@ -83,7 +85,7 @@ public abstract class SpringProperties {
* @param key the property key
* @param value the associated property value, or {@code null} to reset it
*/
public static void setProperty(String key, String value) {
public static void setProperty(String key, @Nullable String value) {
if (value != null) {
localProperties.setProperty(key, value);
}
@@ -98,6 +100,7 @@ public abstract 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) {
String value = localProperties.getProperty(key);
if (value == null) {

View File

@@ -16,6 +16,8 @@
package org.springframework.core;
import org.springframework.lang.Nullable;
/**
* Class that exposes the Spring version. Fetches the
* "Implementation-Version" manifest attribute from the jar file.
@@ -36,6 +38,7 @@ public class SpringVersion {
* or {@code null} if it cannot be determined.
* @see Package#getImplementationVersion()
*/
@Nullable
public static String getVersion() {
Package pkg = SpringVersion.class.getPackage();
return (pkg != null ? pkg.getImplementationVersion() : null);

View File

@@ -21,6 +21,7 @@ import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -55,7 +56,7 @@ abstract class AbstractAliasAwareAnnotationAttributeExtractor<S> implements Anno
* @param source the underlying source of annotation attributes; never {@code null}
*/
AbstractAliasAwareAnnotationAttributeExtractor(
Class<? extends Annotation> annotationType, Object annotatedElement, S source) {
Class<? extends Annotation> annotationType, @Nullable Object annotatedElement, S source) {
Assert.notNull(annotationType, "annotationType must not be null");
Assert.notNull(source, "source must not be null");

View File

@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -149,6 +150,7 @@ public class AnnotatedElementUtils {
* @see #getMetaAnnotationTypes(AnnotatedElement, String)
* @see #hasMetaAnnotationTypes
*/
@Nullable
public static Set<String> getMetaAnnotationTypes(AnnotatedElement element, Class<? extends Annotation> annotationType) {
Assert.notNull(element, "AnnotatedElement must not be null");
Assert.notNull(annotationType, "'annotationType' must not be null");
@@ -170,6 +172,7 @@ public class AnnotatedElementUtils {
* @see #getMetaAnnotationTypes(AnnotatedElement, Class)
* @see #hasMetaAnnotationTypes
*/
@Nullable
public static Set<String> getMetaAnnotationTypes(AnnotatedElement element, String annotationName) {
Assert.notNull(element, "AnnotatedElement must not be null");
Assert.hasLength(annotationName, "'annotationName' must not be null or empty");
@@ -312,6 +315,7 @@ public class AnnotatedElementUtils {
* @see #getMergedAnnotation(AnnotatedElement, Class)
* @see #findMergedAnnotation(AnnotatedElement, Class)
*/
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(
AnnotatedElement element, Class<? extends Annotation> annotationType) {
@@ -340,6 +344,7 @@ public class AnnotatedElementUtils {
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see #getAllAnnotationAttributes(AnnotatedElement, String)
*/
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, String annotationName) {
return getMergedAnnotationAttributes(element, annotationName, false, false);
}
@@ -370,6 +375,7 @@ public class AnnotatedElementUtils {
* @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
* @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
@@ -398,6 +404,7 @@ public class AnnotatedElementUtils {
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement)
*/
@Nullable
public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
Assert.notNull(annotationType, "'annotationType' must not be null");
@@ -504,7 +511,7 @@ public class AnnotatedElementUtils {
* is not a valid container annotation for the supplied {@code annotationType}
*/
public static <A extends Annotation> Set<A> getMergedRepeatableAnnotations(AnnotatedElement element,
Class<A> annotationType, Class<? extends Annotation> containerType) {
Class<A> annotationType, @Nullable Class<? extends Annotation> containerType) {
Assert.notNull(element, "AnnotatedElement must not be null");
Assert.notNull(annotationType, "'annotationType' must not be null");
@@ -535,6 +542,7 @@ public 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(AnnotatedElement element, String annotationName) {
return getAllAnnotationAttributes(element, annotationName, false, false);
}
@@ -557,6 +565,7 @@ public 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,
String annotationName, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) {
@@ -632,6 +641,7 @@ public class AnnotatedElementUtils {
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
@Nullable
public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
Class<? extends Annotation> annotationType, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
@@ -668,6 +678,7 @@ public class AnnotatedElementUtils {
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
@Nullable
public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
@@ -695,6 +706,7 @@ public 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) {
Assert.notNull(annotationType, "'annotationType' must not be null");
@@ -800,7 +812,7 @@ public class AnnotatedElementUtils {
* is not a valid container annotation for the supplied {@code annotationType}
*/
public static <A extends Annotation> Set<A> findMergedRepeatableAnnotations(AnnotatedElement element,
Class<A> annotationType, Class<? extends Annotation> containerType) {
Class<A> annotationType, @Nullable Class<? extends Annotation> containerType) {
Assert.notNull(element, "AnnotatedElement must not be null");
Assert.notNull(annotationType, "'annotationType' must not be null");
@@ -828,6 +840,7 @@ public class AnnotatedElementUtils {
* @param processor the processor to delegate to
* @return the result of the processor, potentially {@code null}
*/
@Nullable
private static <T> T searchWithGetSemantics(AnnotatedElement element, Class<? extends Annotation> annotationType,
String annotationName, Processor<T> processor) {
@@ -848,8 +861,9 @@ public class AnnotatedElementUtils {
* @return the result of the processor, potentially {@code null}
* @since 4.3
*/
@Nullable
private static <T> T searchWithGetSemantics(AnnotatedElement element, Class<? extends Annotation> annotationType,
String annotationName, Class<? extends Annotation> containerType, Processor<T> processor) {
String annotationName, @Nullable Class<? extends Annotation> containerType, Processor<T> processor) {
try {
return searchWithGetSemantics(element, annotationType, annotationName, containerType, processor,
@@ -878,8 +892,9 @@ public class AnnotatedElementUtils {
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor, potentially {@code null}
*/
@Nullable
private static <T> T searchWithGetSemantics(AnnotatedElement element, Class<? extends Annotation> annotationType,
String annotationName, Class<? extends Annotation> containerType, Processor<T> processor,
String annotationName, @Nullable Class<? extends Annotation> containerType, Processor<T> processor,
Set<AnnotatedElement> visited, int metaDepth) {
Assert.notNull(element, "AnnotatedElement must not be null");
@@ -940,9 +955,10 @@ public class AnnotatedElementUtils {
* @return the result of the processor, potentially {@code null}
* @since 4.2
*/
private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement element,
@Nullable
private static <T> T searchWithGetSemanticsInAnnotations(@Nullable AnnotatedElement element,
List<Annotation> annotations, Class<? extends Annotation> annotationType, String annotationName,
Class<? extends Annotation> containerType, Processor<T> processor, Set<AnnotatedElement> visited,
@Nullable Class<? extends Annotation> containerType, Processor<T> processor, Set<AnnotatedElement> visited,
int metaDepth) {
// Search in annotations
@@ -1009,6 +1025,7 @@ public class AnnotatedElementUtils {
* @return the result of the processor, potentially {@code null}
* @since 4.2
*/
@Nullable
private static <T> T searchWithFindSemantics(AnnotatedElement element, Class<? extends Annotation> annotationType,
String annotationName, Processor<T> processor) {
@@ -1029,8 +1046,9 @@ public class AnnotatedElementUtils {
* @return the result of the processor, potentially {@code null}
* @since 4.3
*/
@Nullable
private static <T> T searchWithFindSemantics(AnnotatedElement element, Class<? extends Annotation> annotationType,
String annotationName, Class<? extends Annotation> containerType, Processor<T> processor) {
String annotationName, @Nullable Class<? extends Annotation> containerType, Processor<T> processor) {
if (containerType != null && !processor.aggregates()) {
throw new IllegalArgumentException(
@@ -1065,8 +1083,9 @@ public class AnnotatedElementUtils {
* @return the result of the processor, potentially {@code null}
* @since 4.2
*/
@Nullable
private static <T> T searchWithFindSemantics(AnnotatedElement element, Class<? extends Annotation> annotationType,
String annotationName, Class<? extends Annotation> containerType, Processor<T> processor,
String annotationName, @Nullable Class<? extends Annotation> containerType, Processor<T> processor,
Set<AnnotatedElement> visited, int metaDepth) {
Assert.notNull(element, "AnnotatedElement must not be null");
@@ -1365,7 +1384,8 @@ public class AnnotatedElementUtils {
* @return the result of the processing, or {@code null} to continue
* searching for additional annotations
*/
T process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth);
@Nullable
T process(@Nullable AnnotatedElement annotatedElement, Annotation annotation, int metaDepth);
/**
* Post-process the result returned by the {@link #process} method.
@@ -1379,7 +1399,7 @@ public class AnnotatedElementUtils {
* @param annotation the annotation to post-process
* @param result the result to post-process
*/
void postProcess(AnnotatedElement annotatedElement, Annotation annotation, T result);
void postProcess(@Nullable AnnotatedElement annotatedElement, Annotation annotation, T result);
/**
* Determine if this processor always processes annotations regardless of

View File

@@ -19,6 +19,8 @@ package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* An {@code AnnotationAttributeExtractor} is responsible for
* {@linkplain #getAttributeValue extracting} annotation attribute values
@@ -43,6 +45,7 @@ interface AnnotationAttributeExtractor<S> {
* type supported by this extractor.
* @return the annotated element, or {@code null} if unknown
*/
@Nullable
Object getAnnotatedElement();
/**

View File

@@ -22,6 +22,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -120,7 +121,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
* or {@code null} to just store the annotation type name
* @since 4.3.2
*/
public AnnotationAttributes(String annotationType, ClassLoader classLoader) {
public AnnotationAttributes(String annotationType, @Nullable ClassLoader classLoader) {
Assert.notNull(annotationType, "'annotationType' must not be null");
this.annotationType = getAnnotationType(annotationType, classLoader);
this.displayName = annotationType;
@@ -146,6 +147,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() {
return this.annotationType;
}

View File

@@ -38,6 +38,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ObjectUtils;
@@ -151,6 +152,7 @@ public abstract class AnnotationUtils {
* @since 4.0
*/
@SuppressWarnings("unchecked")
@Nullable
public static <A extends Annotation> A getAnnotation(Annotation ann, Class<A> annotationType) {
if (annotationType.isInstance(ann)) {
return synthesizeAnnotation((A) ann);
@@ -177,6 +179,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) {
try {
A annotation = annotatedElement.getAnnotation(annotationType);
@@ -210,6 +213,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) {
Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
return getAnnotation((AnnotatedElement) resolvedMethod, annotationType);
@@ -226,6 +230,7 @@ public abstract class AnnotationUtils {
* @since 4.0.8
* @see AnnotatedElement#getAnnotations()
*/
@Nullable
public static Annotation[] getAnnotations(AnnotatedElement annotatedElement) {
try {
return synthesizeAnnotationArray(annotatedElement.getAnnotations(), annotatedElement);
@@ -248,6 +253,7 @@ public abstract class AnnotationUtils {
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
* @see AnnotatedElement#getAnnotations()
*/
@Nullable
public static Annotation[] getAnnotations(Method method) {
try {
return synthesizeAnnotationArray(BridgeMethodResolver.findBridgedMethod(method).getAnnotations(), method);
@@ -285,6 +291,7 @@ public abstract class AnnotationUtils {
* @see java.lang.annotation.Repeatable
* @see java.lang.reflect.AnnotatedElement#getAnnotationsByType
*/
@Nullable
public static <A extends Annotation> Set<A> getRepeatableAnnotations(AnnotatedElement annotatedElement,
Class<A> annotationType) {
@@ -322,7 +329,7 @@ public abstract class AnnotationUtils {
* @see java.lang.reflect.AnnotatedElement#getAnnotationsByType
*/
public static <A extends Annotation> Set<A> getRepeatableAnnotations(AnnotatedElement annotatedElement,
Class<A> annotationType, Class<? extends Annotation> containerAnnotationType) {
Class<A> annotationType, @Nullable Class<? extends Annotation> containerAnnotationType) {
Set<A> annotations = getDeclaredRepeatableAnnotations(annotatedElement, annotationType, containerAnnotationType);
if (!annotations.isEmpty()) {
@@ -404,7 +411,7 @@ public abstract class AnnotationUtils {
* @see java.lang.reflect.AnnotatedElement#getDeclaredAnnotationsByType
*/
public static <A extends Annotation> Set<A> getDeclaredRepeatableAnnotations(AnnotatedElement annotatedElement,
Class<A> annotationType, Class<? extends Annotation> containerAnnotationType) {
Class<A> annotationType, @Nullable Class<? extends Annotation> containerAnnotationType) {
return getRepeatableAnnotations(annotatedElement, annotationType, containerAnnotationType, true);
}
@@ -430,7 +437,7 @@ public abstract class AnnotationUtils {
* @see java.lang.annotation.Repeatable
*/
private static <A extends Annotation> Set<A> getRepeatableAnnotations(AnnotatedElement annotatedElement,
Class<A> annotationType, Class<? extends Annotation> containerAnnotationType, boolean declaredMode) {
Class<A> annotationType, @Nullable Class<? extends Annotation> containerAnnotationType, boolean declaredMode) {
Assert.notNull(annotatedElement, "AnnotatedElement must not be null");
Assert.notNull(annotationType, "Annotation type must not be null");
@@ -463,6 +470,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(AnnotatedElement annotatedElement, Class<A> annotationType) {
Assert.notNull(annotatedElement, "AnnotatedElement must not be null");
if (annotationType == null) {
@@ -485,6 +493,7 @@ public abstract class AnnotationUtils {
* @return the first matching annotation, or {@code null} if not found
* @since 4.2
*/
@Nullable
private static <A extends Annotation> A findAnnotation(
AnnotatedElement annotatedElement, Class<A> annotationType, Set<Annotation> visited) {
try {
@@ -524,6 +533,7 @@ public abstract class AnnotationUtils {
* @see #getAnnotation(Method, Class)
*/
@SuppressWarnings("unchecked")
@Nullable
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
Assert.notNull(method, "Method must not be null");
if (annotationType == null) {
@@ -631,6 +641,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, Class<A> annotationType) {
return findAnnotation(clazz, annotationType, true);
}
@@ -646,6 +657,7 @@ public abstract class AnnotationUtils {
* @since 4.2.1
*/
@SuppressWarnings("unchecked")
@Nullable
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, boolean synthesize) {
Assert.notNull(clazz, "Class must not be null");
if (annotationType == null) {
@@ -673,6 +685,7 @@ public abstract class AnnotationUtils {
* @param visited the set of annotations that have already been visited
* @return the first matching annotation, or {@code null} if not found
*/
@Nullable
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
try {
A annotation = clazz.getDeclaredAnnotation(annotationType);
@@ -730,7 +743,8 @@ public abstract class AnnotationUtils {
* @see #findAnnotationDeclaringClassForTypes(List, Class)
* @see #isAnnotationDeclaredLocally(Class, Class)
*/
public static Class<?> findAnnotationDeclaringClass(Class<? extends Annotation> annotationType, Class<?> clazz) {
@Nullable
public static Class<?> findAnnotationDeclaringClass(Class<? extends Annotation> annotationType, @Nullable Class<?> clazz) {
Assert.notNull(annotationType, "Annotation type must not be null");
if (clazz == null || Object.class == clazz) {
return null;
@@ -765,7 +779,8 @@ public abstract class AnnotationUtils {
* @see #findAnnotationDeclaringClass(Class, Class)
* @see #isAnnotationDeclaredLocally(Class, Class)
*/
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes, Class<?> clazz) {
@Nullable
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes, @Nullable Class<?> clazz) {
Assert.notEmpty(annotationTypes, "List of annotation types must not be empty");
if (clazz == null || Object.class == clazz) {
return null;
@@ -966,7 +981,7 @@ public abstract class AnnotationUtils {
* @since 4.2
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
*/
public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedElement, Annotation annotation) {
public static AnnotationAttributes getAnnotationAttributes(@Nullable AnnotatedElement annotatedElement, Annotation annotation) {
return getAnnotationAttributes(annotatedElement, annotation, false, false);
}
@@ -988,7 +1003,7 @@ public abstract class AnnotationUtils {
* and corresponding attribute values as values (never {@code null})
* @since 4.2
*/
public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedElement,
public static AnnotationAttributes getAnnotationAttributes(@Nullable AnnotatedElement annotatedElement,
Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
return getAnnotationAttributes(
@@ -1032,7 +1047,7 @@ public abstract class AnnotationUtils {
* @since 4.2
* @see #postProcessAnnotationAttributes
*/
static AnnotationAttributes retrieveAnnotationAttributes(Object annotatedElement, Annotation annotation,
static AnnotationAttributes retrieveAnnotationAttributes(@Nullable Object annotatedElement, Annotation annotation,
boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
Class<? extends Annotation> annotationType = annotation.annotationType();
@@ -1076,7 +1091,7 @@ public abstract class AnnotationUtils {
* {@code Annotation} instances
* @return the adapted value, or the original value if no adaptation is needed
*/
static Object adaptValue(Object annotatedElement, Object value, boolean classValuesAsString,
static Object adaptValue(@Nullable Object annotatedElement, Object value, boolean classValuesAsString,
boolean nestedAnnotationsAsMap) {
if (classValuesAsString) {
@@ -1173,7 +1188,7 @@ public abstract class AnnotationUtils {
* @see #postProcessAnnotationAttributes(Object, AnnotationAttributes, boolean, boolean)
* @see #getDefaultValue(Class, String)
*/
public static void postProcessAnnotationAttributes(Object annotatedElement,
public static void postProcessAnnotationAttributes(@Nullable Object annotatedElement,
AnnotationAttributes attributes, boolean classValuesAsString) {
postProcessAnnotationAttributes(annotatedElement, attributes, classValuesAsString, false);
@@ -1199,7 +1214,7 @@ public abstract class AnnotationUtils {
* @see #retrieveAnnotationAttributes(Object, Annotation, boolean, boolean)
* @see #getDefaultValue(Class, String)
*/
static void postProcessAnnotationAttributes(Object annotatedElement,
static void postProcessAnnotationAttributes(@Nullable Object annotatedElement,
AnnotationAttributes attributes, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
// Abort?
@@ -1287,6 +1302,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) {
return getValue(annotation, VALUE);
}
@@ -1301,6 +1317,7 @@ public abstract class AnnotationUtils {
* @see #getValue(Annotation)
* @see #rethrowAnnotationConfigurationException(Throwable)
*/
@Nullable
public static Object getValue(Annotation annotation, String attributeName) {
if (annotation == null || !StringUtils.hasText(attributeName)) {
return null;
@@ -1328,6 +1345,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) {
return getDefaultValue(annotation, VALUE);
}
@@ -1339,6 +1357,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(Annotation annotation, String attributeName) {
if (annotation == null) {
return null;
@@ -1353,6 +1372,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) {
return getDefaultValue(annotationType, VALUE);
}
@@ -1365,6 +1385,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(Class<? extends Annotation> annotationType, String attributeName) {
if (annotationType == null || !StringUtils.hasText(attributeName)) {
return null;
@@ -1392,7 +1413,8 @@ public abstract class AnnotationUtils {
* @since 4.2
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
*/
static <A extends Annotation> A synthesizeAnnotation(A annotation) {
@Nullable
static <A extends Annotation> A synthesizeAnnotation(@Nullable A annotation) {
return synthesizeAnnotation(annotation, null);
}
@@ -1413,7 +1435,8 @@ public abstract class AnnotationUtils {
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
* @see #synthesizeAnnotation(Class)
*/
public static <A extends Annotation> A synthesizeAnnotation(A annotation, AnnotatedElement annotatedElement) {
@Nullable
public static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable AnnotatedElement annotatedElement) {
return synthesizeAnnotation(annotation, (Object) annotatedElement);
}
@@ -1472,8 +1495,9 @@ public abstract class AnnotationUtils {
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
*/
@SuppressWarnings("unchecked")
@Nullable
public static <A extends Annotation> A synthesizeAnnotation(Map<String, Object> attributes,
Class<A> annotationType, AnnotatedElement annotatedElement) {
Class<A> annotationType, @Nullable AnnotatedElement annotatedElement) {
Assert.notNull(annotationType, "'annotationType' must not be null");
if (attributes == null) {
@@ -1503,6 +1527,7 @@ public abstract class AnnotationUtils {
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
*/
@Nullable
public static <A extends Annotation> A synthesizeAnnotation(Class<A> annotationType) {
return synthesizeAnnotation(Collections.<String, Object> emptyMap(), annotationType, null);
}
@@ -1523,7 +1548,8 @@ public abstract class AnnotationUtils {
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
*/
static Annotation[] synthesizeAnnotationArray(Annotation[] annotations, Object annotatedElement) {
@Nullable
static Annotation[] synthesizeAnnotationArray(@Nullable Annotation[] annotations, @Nullable Object annotatedElement) {
if (annotations == null) {
return null;
}
@@ -1554,7 +1580,8 @@ public abstract class AnnotationUtils {
* @see #synthesizeAnnotationArray(Annotation[], Object)
*/
@SuppressWarnings("unchecked")
static <A extends Annotation> A[] synthesizeAnnotationArray(Map<String, Object>[] maps, Class<A> annotationType) {
@Nullable
static <A extends Annotation> A[] synthesizeAnnotationArray(@Nullable Map<String, Object>[] maps, Class<A> annotationType) {
Assert.notNull(annotationType, "'annotationType' must not be null");
if (maps == null) {
return null;
@@ -1705,7 +1732,8 @@ public abstract class AnnotationUtils {
* {@code @AliasFor} is detected
* @since 4.2
*/
static String getAttributeOverrideName(Method attribute, Class<? extends Annotation> metaAnnotationType) {
@Nullable
static String getAttributeOverrideName(Method attribute, @Nullable Class<? extends Annotation> metaAnnotationType) {
Assert.notNull(attribute, "attribute must not be null");
Assert.notNull(metaAnnotationType, "metaAnnotationType must not be null");
Assert.isTrue(Annotation.class != metaAnnotationType,
@@ -1753,6 +1781,7 @@ public abstract class AnnotationUtils {
* @return the annotation if found; {@code null} otherwise
* @since 4.2
*/
@Nullable
static Annotation getAnnotation(AnnotatedElement element, String annotationName) {
for (Annotation annotation : element.getAnnotations()) {
if (annotation.annotationType().getName().equals(annotationName)) {
@@ -1790,6 +1819,7 @@ public abstract class AnnotationUtils {
* {@code null}.
* @since 4.2
*/
@Nullable
static Class<? extends Annotation> resolveContainerAnnotationType(Class<? extends Annotation> annotationType) {
Repeatable repeatable = getAnnotation(annotationType, Repeatable.class);
return (repeatable != null ? repeatable.value() : null);
@@ -1994,6 +2024,7 @@ public abstract class AnnotationUtils {
* is not annotated with {@code @AliasFor}
* @see #validateAgainst
*/
@Nullable
public static AliasDescriptor from(Method attribute) {
AliasDescriptor descriptor = aliasDescriptorCache.get(attribute);
if (descriptor != null) {
@@ -2180,6 +2211,7 @@ public abstract class AnnotationUtils {
return otherDescriptors;
}
@Nullable
public String getAttributeOverrideName(Class<? extends Annotation> metaAnnotationType) {
Assert.notNull(metaAnnotationType, "metaAnnotationType must not be null");
Assert.isTrue(Annotation.class != metaAnnotationType,
@@ -2196,6 +2228,7 @@ public abstract class AnnotationUtils {
return null;
}
@Nullable
private AliasDescriptor getAttributeOverrideDescriptor() {
if (this.isAliasPair) {
return null;
@@ -2219,6 +2252,7 @@ public abstract class AnnotationUtils {
* @throws AnnotationConfigurationException if invalid configuration of
* {@code @AliasFor} is detected
*/
@Nullable
private String getAliasedAttributeName(AliasFor aliasFor, Method attribute) {
String attributeName = aliasFor.attribute();
String value = aliasFor.value();

View File

@@ -19,6 +19,7 @@ package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;
/**
@@ -41,7 +42,7 @@ class DefaultAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAt
* @param annotatedElement the element that is annotated with the supplied
* annotation; may be {@code null} if unknown
*/
DefaultAnnotationAttributeExtractor(Annotation annotation, Object annotatedElement) {
DefaultAnnotationAttributeExtractor(Annotation annotation, @Nullable Object annotatedElement) {
super(annotation.annotationType(), annotatedElement, annotation);
}

View File

@@ -24,6 +24,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -52,7 +53,7 @@ class MapAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAttrib
* of the supplied type; may be {@code null} if unknown
*/
MapAnnotationAttributeExtractor(Map<String, Object> attributes, Class<? extends Annotation> annotationType,
AnnotatedElement annotatedElement) {
@Nullable AnnotatedElement annotatedElement) {
super(annotationType, annotatedElement, enrichAndValidateAttributes(attributes, annotationType));
}

View File

@@ -18,6 +18,7 @@ package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -53,6 +54,7 @@ public abstract class OrderUtils {
* @return the order value, or {@code null} if none can be found
* @see #getPriority(Class)
*/
@Nullable
public static Integer getOrder(Class<?> type) {
return getOrder(type, null);
}
@@ -83,6 +85,7 @@ public abstract class OrderUtils {
* @param type the type to handle
* @return the priority value if the annotation is declared, or {@code null} if none
*/
@Nullable
public static Integer getPriority(Class<?> type) {
if (priorityAnnotationType != null) {
Annotation priority = AnnotationUtils.findAnnotation(type, priorityAnnotationType);

View File

@@ -2,4 +2,7 @@
* Core support package for annotations, meta-annotations, and composed
* annotations with attribute overrides.
*/
@NonNullApi
package org.springframework.core.annotation;
import org.springframework.lang.NonNullApi;

View File

@@ -17,6 +17,7 @@
package org.springframework.core.codec;
import org.springframework.core.NestedRuntimeException;
import org.springframework.lang.Nullable;
/**
* General error that indicates a problem while encoding and decoding to and
@@ -42,7 +43,7 @@ public class CodecException extends NestedRuntimeException {
* @param msg the detail message
* @param cause root cause for the exception, if any
*/
public CodecException(String msg, Throwable cause) {
public CodecException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -25,6 +25,7 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.lang.Nullable;
import org.springframework.util.MimeType;
/**
@@ -45,7 +46,7 @@ public interface Decoder<T> {
* @param mimeType the mime type associated with the stream to decode, can be {@code null} if not specified.
* @return {@code true} if supported, {@code false} otherwise
*/
boolean canDecode(ResolvableType elementType, MimeType mimeType);
boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType);
/**
* Decode a {@link DataBuffer} input stream into a Flux of {@code T}.
@@ -58,7 +59,7 @@ public interface Decoder<T> {
* @return the output stream with decoded elements
*/
Flux<T> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
MimeType mimeType, Map<String, Object> hints);
@Nullable MimeType mimeType, Map<String, Object> hints);
/**
* Decode a {@link DataBuffer} input stream into a Mono of {@code T}.
@@ -71,7 +72,7 @@ public interface Decoder<T> {
* @return the output stream with the decoded element
*/
Mono<T> decodeToMono(Publisher<DataBuffer> inputStream, ResolvableType elementType,
MimeType mimeType, Map<String, Object> hints);
@Nullable MimeType mimeType, Map<String, Object> hints);
/**
* Return the list of MIME types this decoder supports.

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.core.codec;
import org.springframework.lang.Nullable;
/**
* Indicates an issue with decoding the input stream with a focus on content
* related issues such as a parse failure. As opposed to more general I/O
@@ -45,7 +47,7 @@ public class DecodingException extends CodecException {
* @param msg the detail message
* @param cause root cause for the exception, if any
*/
public DecodingException(String msg, Throwable cause) {
public DecodingException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -26,6 +26,7 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.MimeType;
/**
@@ -46,7 +47,7 @@ public interface Encoder<T> {
* @param mimeType the MIME type for the output stream, can be {@code null} if not specified.
* @return {@code true} if supported, {@code false} otherwise
*/
boolean canEncode(ResolvableType elementType, MimeType mimeType);
boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType);
/**
* Encode a stream of Objects of type {@code T} into a {@link DataBuffer}
@@ -63,7 +64,7 @@ public interface Encoder<T> {
* @return the output stream
*/
Flux<DataBuffer> encode(Publisher<? extends T> inputStream, DataBufferFactory bufferFactory,
ResolvableType elementType, MimeType mimeType, Map<String, Object> hints);
ResolvableType elementType, @Nullable MimeType mimeType, Map<String, Object> hints);
/**
* Return the list of mime types this encoder supports.

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.core.codec;
import org.springframework.lang.Nullable;
/**
* Indicates an issue with encoding the input Object stream with a focus on
* not being able to encode Objects. As opposed to a more general I/O errors
@@ -41,7 +43,7 @@ public class EncodingException extends CodecException {
* @param msg the detail message
* @param cause root cause for the exception, if any
*/
public EncodingException(String msg, Throwable cause) {
public EncodingException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -3,4 +3,7 @@
* {@link org.springframework.core.codec.Decoder} abstractions to convert
* between a reactive stream of bytes and Java objects.
*/
@NonNullApi
package org.springframework.core.codec;
import org.springframework.lang.NonNullApi;

View File

@@ -16,6 +16,8 @@
package org.springframework.core.convert;
import org.springframework.lang.Nullable;
/**
* A service interface for type conversion. This is the entry point into the convert system.
* Call {@link #convert(Object, Class)} to perform a thread-safe type conversion using this system.
@@ -40,7 +42,7 @@ public interface ConversionService {
* @return {@code true} if a conversion can be performed, {@code false} if not
* @throws IllegalArgumentException if {@code targetType} is {@code null}
*/
boolean canConvert(Class<?> sourceType, Class<?> targetType);
boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);
/**
* Return {@code true} if objects of {@code sourceType} can be converted to the {@code targetType}.
@@ -60,7 +62,7 @@ public interface ConversionService {
* {@code false} if not
* @throws IllegalArgumentException if {@code targetType} is {@code null}
*/
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
/**
* Convert the given {@code source} to the specified {@code targetType}.
@@ -70,7 +72,7 @@ public interface ConversionService {
* @throws ConversionException if a conversion exception occurred
* @throws IllegalArgumentException if targetType is {@code null}
*/
<T> T convert(Object source, Class<T> targetType);
<T> T convert(@Nullable Object source, Class<T> targetType);
/**
* Convert the given {@code source} to the specified {@code targetType}.
@@ -85,6 +87,6 @@ public interface ConversionService {
* @throws IllegalArgumentException if targetType is {@code null},
* or {@code sourceType} is {@code null} but source is not {@code null}
*/
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
}

View File

@@ -25,6 +25,7 @@ import java.util.Map;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -171,6 +172,7 @@ public final class Property {
return write;
}
@Nullable
private MethodParameter resolveReadMethodParameter() {
if (getReadMethod() == null) {
return null;
@@ -178,6 +180,7 @@ public final class Property {
return resolveParameterType(new MethodParameter(getReadMethod(), -1));
}
@Nullable
private MethodParameter resolveWriteMethodParameter() {
if (getWriteMethod() == null) {
return null;
@@ -214,6 +217,7 @@ public final class Property {
}
}
@Nullable
private Field getField() {
String name = getName();
if (!StringUtils.hasLength(name)) {

View File

@@ -30,6 +30,7 @@ import java.util.stream.Stream;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -117,7 +118,7 @@ public class TypeDescriptor implements Serializable {
* @param annotations the type annotations
* @since 4.0
*/
protected TypeDescriptor(ResolvableType resolvableType, Class<?> type, Annotation[] annotations) {
protected TypeDescriptor(ResolvableType resolvableType, @Nullable Class<?> type, Annotation[] annotations) {
this.resolvableType = resolvableType;
this.type = (type != null ? type : resolvableType.resolve(Object.class));
this.annotatedElement = new AnnotatedElementAdapter(annotations);
@@ -181,7 +182,7 @@ public class TypeDescriptor implements Serializable {
* @return this TypeDescriptor narrowed (returns a copy with its type updated to the
* class of the provided value)
*/
public TypeDescriptor narrow(Object value) {
public TypeDescriptor narrow(@Nullable Object value) {
if (value == null) {
return this;
}
@@ -197,7 +198,8 @@ public class TypeDescriptor implements Serializable {
* @throws IllegalArgumentException if this type is not assignable to the super-type
* @since 3.2
*/
public TypeDescriptor upcast(Class<?> superType) {
@Nullable
public TypeDescriptor upcast(@Nullable Class<?> superType) {
if (superType == null) {
return null;
}
@@ -250,6 +252,7 @@ public class TypeDescriptor implements Serializable {
* @return the annotation, or {@code null} if no such annotation exists on this type descriptor
*/
@SuppressWarnings("unchecked")
@Nullable
public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
if (this.annotatedElement.isEmpty()) {
// Shortcut: AnnotatedElementUtils would have to expect AnnotatedElement.getAnnotations()
@@ -323,6 +326,7 @@ public class TypeDescriptor implements Serializable {
* Collection but its element type is not parameterized
* @throws IllegalStateException if this type is not a {@code java.util.Collection} or array type
*/
@Nullable
public TypeDescriptor getElementTypeDescriptor() {
if (getResolvableType().isArray()) {
return new TypeDescriptor(getResolvableType().getComponentType(), null, getAnnotations());
@@ -370,6 +374,7 @@ public class TypeDescriptor implements Serializable {
* but its key type is not parameterized
* @throws IllegalStateException if this type is not a {@code java.util.Map}
*/
@Nullable
public TypeDescriptor getMapKeyTypeDescriptor() {
Assert.state(isMap(), "Not a [java.util.Map]");
return getRelatedIfResolvable(this, getResolvableType().asMap().getGeneric(0));
@@ -405,6 +410,7 @@ public class TypeDescriptor implements Serializable {
* but its value type is not parameterized
* @throws IllegalStateException if this type is not a {@code java.util.Map}
*/
@Nullable
public TypeDescriptor getMapValueTypeDescriptor() {
Assert.state(isMap(), "Not a [java.util.Map]");
return getRelatedIfResolvable(this, getResolvableType().asMap().getGeneric(1));
@@ -431,6 +437,7 @@ public class TypeDescriptor implements Serializable {
return narrow(mapValue, getMapValueTypeDescriptor());
}
@Nullable
private TypeDescriptor narrow(Object value, TypeDescriptor typeDescriptor) {
if (typeDescriptor != null) {
return typeDescriptor.narrow(value);
@@ -517,7 +524,8 @@ public class TypeDescriptor implements Serializable {
* @param source the source object
* @return the type descriptor
*/
public static TypeDescriptor forObject(Object source) {
@Nullable
public static TypeDescriptor forObject(@Nullable Object source) {
return (source != null ? valueOf(source.getClass()) : null);
}
@@ -531,7 +539,7 @@ public class TypeDescriptor implements Serializable {
* @param type the class (may be {@code null} to indicate {@code Object.class})
* @return the corresponding type descriptor
*/
public static TypeDescriptor valueOf(Class<?> type) {
public static TypeDescriptor valueOf(@Nullable Class<?> type) {
if (type == null) {
type = Object.class;
}
@@ -594,7 +602,8 @@ public class TypeDescriptor implements Serializable {
* @return an array {@link TypeDescriptor} or {@code null} if {@code elementTypeDescriptor} is {@code null}
* @since 3.2.1
*/
public static TypeDescriptor array(TypeDescriptor elementTypeDescriptor) {
@Nullable
public static TypeDescriptor array(@Nullable TypeDescriptor elementTypeDescriptor) {
if (elementTypeDescriptor == null) {
return null;
}
@@ -624,6 +633,7 @@ public class TypeDescriptor implements Serializable {
* {@link MethodParameter} argument is not 1, or if the types up to the
* specified nesting level are not of collection, array, or map types
*/
@Nullable
public static TypeDescriptor nested(MethodParameter methodParameter, int nestingLevel) {
if (methodParameter.getNestingLevel() != 1) {
throw new IllegalArgumentException("MethodParameter nesting level must be 1: " +
@@ -652,6 +662,7 @@ public class TypeDescriptor implements Serializable {
* @throws IllegalArgumentException if the types up to the specified nesting
* level are not of collection, array, or map types
*/
@Nullable
public static TypeDescriptor nested(Field field, int nestingLevel) {
return nested(new TypeDescriptor(field), nestingLevel);
}
@@ -677,10 +688,12 @@ public class TypeDescriptor implements Serializable {
* @throws IllegalArgumentException if the types up to the specified nesting
* level are not of collection, array, or map types
*/
@Nullable
public static TypeDescriptor nested(Property property, int nestingLevel) {
return nested(new TypeDescriptor(property), nestingLevel);
}
@Nullable
private static TypeDescriptor nested(TypeDescriptor typeDescriptor, int nestingLevel) {
ResolvableType nested = typeDescriptor.resolvableType;
for (int i = 0; i < nestingLevel; i++) {
@@ -698,6 +711,7 @@ public class TypeDescriptor implements Serializable {
return getRelatedIfResolvable(typeDescriptor, nested);
}
@Nullable
private static TypeDescriptor getRelatedIfResolvable(TypeDescriptor source, ResolvableType type) {
if (type.resolve() == null) {
return null;

View File

@@ -16,6 +16,8 @@
package org.springframework.core.convert.converter;
import org.springframework.lang.Nullable;
/**
* A converter converts a source object of type {@code S} to a target of type {@code T}.
*
@@ -37,6 +39,7 @@ public interface Converter<S, T> {
* @return the converted object, which must be an instance of {@code T} (potentially {@code null})
* @throws IllegalArgumentException if the source cannot be converted to the desired target type
*/
@Nullable
T convert(S source);
}

View File

@@ -19,6 +19,7 @@ package org.springframework.core.convert.converter;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -52,6 +53,7 @@ public interface GenericConverter {
* <p>For {@link ConditionalConverter conditional converters} this method may return
* {@code null} to indicate all source-to-target pairs should be considered.
*/
@Nullable
Set<ConvertiblePair> getConvertibleTypes();
/**
@@ -61,7 +63,8 @@ public interface GenericConverter {
* @param targetType the type descriptor of the field we are converting to
* @return the converted object
*/
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
@Nullable
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
/**

View File

@@ -1,4 +1,7 @@
/**
* SPI to implement Converters for the type conversion system.
*/
@NonNullApi
package org.springframework.core.convert.converter;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Type conversion system API.
*/
@NonNullApi
package org.springframework.core.convert;
import org.springframework.lang.NonNullApi;

View File

@@ -42,6 +42,7 @@ import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
@@ -157,7 +158,7 @@ public class GenericConversionService implements ConfigurableConversionService {
* @throws IllegalArgumentException if targetType is {@code null}
* @since 3.2
*/
public boolean canBypassConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
public boolean canBypassConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
Assert.notNull(targetType, "Target type to convert to cannot be null");
if (sourceType == null) {
return true;
@@ -205,7 +206,8 @@ public class GenericConversionService implements ConfigurableConversionService {
* @throws IllegalArgumentException if targetType is {@code null},
* or sourceType is {@code null} but source is not {@code null}
*/
public Object convert(Object source, TypeDescriptor targetType) {
@Nullable
public Object convert(@Nullable Object source, TypeDescriptor targetType) {
return convert(source, TypeDescriptor.forObject(source), targetType);
}
@@ -227,6 +229,7 @@ public class GenericConversionService implements ConfigurableConversionService {
* @param targetType the target type to convert to
* @return the converted null object
*/
@Nullable
protected Object convertNullSource(TypeDescriptor sourceType, TypeDescriptor targetType) {
if (targetType.getObjectType() == Optional.class) {
return Optional.empty();
@@ -245,6 +248,7 @@ public class GenericConversionService implements ConfigurableConversionService {
* or {@code null} if no suitable converter was found
* @see #getDefaultConverter(TypeDescriptor, TypeDescriptor)
*/
@Nullable
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
GenericConverter converter = this.converterCache.get(key);
@@ -274,6 +278,7 @@ public class GenericConversionService implements ConfigurableConversionService {
* @param targetType the target type to convert to
* @return the default generic converter that will perform the conversion
*/
@Nullable
protected GenericConverter getDefaultConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
return (sourceType.isAssignableTo(targetType) ? NO_OP_CONVERTER : null);
}
@@ -281,6 +286,7 @@ public class GenericConversionService implements ConfigurableConversionService {
// Internal helpers
@Nullable
private ResolvableType[] getRequiredTypeInfo(Class<?> converterClass, Class<?> genericIfc) {
ResolvableType resolvableType = ResolvableType.forClass(converterClass).as(genericIfc);
ResolvableType[] generics = resolvableType.getGenerics();
@@ -299,6 +305,7 @@ public class GenericConversionService implements ConfigurableConversionService {
this.converterCache.clear();
}
@Nullable
private Object handleConverterNotFound(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
assertNotPrimitiveTargetType(sourceType, targetType);
@@ -526,6 +533,7 @@ public class GenericConversionService implements ConfigurableConversionService {
* @param targetType the target type
* @return a matching {@link GenericConverter}, or {@code null} if none found
*/
@Nullable
public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
// Search the full type hierarchy
List<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType());
@@ -542,6 +550,7 @@ public class GenericConversionService implements ConfigurableConversionService {
return null;
}
@Nullable
private GenericConverter getRegisteredConverter(TypeDescriptor sourceType,
TypeDescriptor targetType, ConvertiblePair convertiblePair) {
@@ -647,6 +656,7 @@ public class GenericConversionService implements ConfigurableConversionService {
this.converters.addFirst(converter);
}
@Nullable
public GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
for (GenericConverter converter : this.converters) {
if (!(converter instanceof ConditionalGenericConverter) ||

View File

@@ -24,6 +24,7 @@ import java.util.Set;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -71,7 +72,7 @@ final class IdToEntityConverter implements ConditionalGenericConverter {
return ReflectionUtils.invokeMethod(finder, source, id);
}
@Nullable
private Method getFinder(Class<?> entityClass) {
String finderMethod = "find" + getEntityName(entityClass);
Method[] methods;

View File

@@ -1,4 +1,7 @@
/**
* Default implementation of the type conversion system.
*/
@NonNullApi
package org.springframework.core.convert.support;
import org.springframework.lang.NonNullApi;

View File

@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.PropertyPlaceholderHelper;
@@ -267,6 +268,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
* @param key the property name to resolve
* @return the property value or {@code null} if none found
*/
@Nullable
protected abstract String getPropertyAsRawString(String key);
}

View File

@@ -23,6 +23,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
/**
* A simple representation of command line arguments, broken into "option arguments" and
* "non-option arguments".
@@ -42,7 +44,7 @@ class CommandLineArgs {
* The given value may be {@code null}, indicating that the option was specified
* without an associated value (e.g. "--foo" vs. "--foo=bar").
*/
public void addOptionArg(String optionName, String optionValue) {
public void addOptionArg(String optionName, @Nullable String optionValue) {
if (!this.optionArgs.containsKey(optionName)) {
this.optionArgs.put(optionName, new ArrayList<>());
}
@@ -70,6 +72,7 @@ class CommandLineArgs {
* that the option was not present; empty list signifies that no values were associated
* with this option.
*/
@Nullable
public List<String> getOptionValues(String optionName) {
return this.optionArgs.get(optionName);
}

View File

@@ -19,6 +19,7 @@ package org.springframework.core.env;
import java.util.Collection;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@@ -305,6 +306,7 @@ public abstract class CommandLinePropertySource<T> extends EnumerablePropertySou
* <li>if the option is not present, return {@code null}</li>
* </ul>
*/
@Nullable
protected abstract List<String> getOptionValues(String name);
/**

View File

@@ -17,6 +17,7 @@
package org.springframework.core.env;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.lang.Nullable;
/**
* Configuration interface to be implemented by most if not all {@link PropertyResolver}
@@ -71,7 +72,7 @@ public interface ConfigurablePropertyResolver extends PropertyResolver {
* resolver and their associated default value, or {@code null} if no such
* special character should be processed as a value separator.
*/
void setValueSeparator(String valueSeparator);
void setValueSeparator(@Nullable String valueSeparator);
/**
* Set whether to throw an exception when encountering an unresolvable placeholder

View File

@@ -16,6 +16,8 @@
package org.springframework.core.env;
import org.springframework.lang.Nullable;
/**
* Interface indicating a component that contains and exposes an {@link Environment} reference.
*
@@ -44,6 +46,7 @@ public interface EnvironmentCapable {
* Return the {@link Environment} associated with this component
* (may be {@code null} or a default environment).
*/
@Nullable
Environment getEnvironment();
}

View File

@@ -23,6 +23,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@@ -154,6 +155,7 @@ public class MutablePropertySources implements PropertySources {
* Remove and return the property source with the given name, {@code null} if not found.
* @param name the name of the property source to find and remove
*/
@Nullable
public PropertySource<?> remove(String name) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Removing [%s] PropertySource", name));

View File

@@ -16,6 +16,8 @@
package org.springframework.core.env;
import org.springframework.lang.Nullable;
/**
* Interface for resolving properties against any underlying source.
*
@@ -41,6 +43,7 @@ public interface PropertyResolver {
* @see #getProperty(String, Class)
* @see #getRequiredProperty(String)
*/
@Nullable
String getProperty(String key);
/**
@@ -60,6 +63,7 @@ public interface PropertyResolver {
* @param targetType the expected type of the property value
* @see #getRequiredProperty(String, Class)
*/
@Nullable
<T> T getProperty(String key, Class<T> targetType);
/**

View File

@@ -19,6 +19,7 @@ package org.springframework.core.env;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -117,6 +118,7 @@ public abstract class PropertySource<T> {
* @param name the property to find
* @see PropertyResolver#getRequiredProperty(String)
*/
@Nullable
public abstract Object getProperty(String name);

View File

@@ -16,6 +16,8 @@
package org.springframework.core.env;
import org.springframework.lang.Nullable;
/**
* Holder containing one or more {@link PropertySource} objects.
*
@@ -34,6 +36,7 @@ public interface PropertySources extends Iterable<PropertySource<?>> {
* Return the property source with the given name, {@code null} if not found.
* @param name the {@linkplain PropertySource#getName() name of the property source} to find
*/
@Nullable
PropertySource<?> get(String name);
}

View File

@@ -16,6 +16,8 @@
package org.springframework.core.env;
import org.springframework.lang.Nullable;
/**
* {@link PropertyResolver} implementation that resolves property values against
* an underlying set of {@link PropertySources}.
@@ -68,6 +70,7 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
return getProperty(key, String.class, false);
}
@Nullable
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
for (PropertySource<?> propertySource : this.propertySources) {

View File

@@ -18,6 +18,7 @@ package org.springframework.core.env;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -117,6 +118,7 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
return name;
}
@Nullable
private String checkPropertyName(String name) {
// Check name as-is
if (containsKey(name)) {

View File

@@ -2,4 +2,7 @@
* Spring's environment abstraction consisting of bean definition
* profile and hierarchical property source support.
*/
@NonNullApi
package org.springframework.core.env;
import org.springframework.lang.NonNullApi;

View File

@@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -72,7 +73,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
* or {@code null} for the thread context class loader
* @see ClassLoader#getResourceAsStream(String)
*/
public ClassPathResource(String path, ClassLoader classLoader) {
public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
Assert.notNull(path, "Path must not be null");
String pathToUse = StringUtils.cleanPath(path);
if (pathToUse.startsWith("/")) {
@@ -90,7 +91,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
* @param clazz the class to load resources with
* @see java.lang.Class#getResourceAsStream
*/
public ClassPathResource(String path, Class<?> clazz) {
public ClassPathResource(String path, @Nullable Class<?> clazz) {
Assert.notNull(path, "Path must not be null");
this.path = StringUtils.cleanPath(path);
this.clazz = clazz;
@@ -103,7 +104,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
* @param classLoader the class loader to load the resource with, if any
* @param clazz the class to load resources with, if any
*/
protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {
protected ClassPathResource(String path, @Nullable ClassLoader classLoader, @Nullable Class<?> clazz) {
this.path = StringUtils.cleanPath(path);
this.classLoader = classLoader;
this.clazz = clazz;
@@ -139,6 +140,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
* Resolves a URL for the underlying class path resource.
* @return the resolved URL, or {@code null} if not resolvable
*/
@Nullable
protected URL resolveURL() {
if (this.clazz != null) {
return this.clazz.getResource(this.path);

View File

@@ -24,6 +24,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -67,7 +68,7 @@ public class DefaultResourceLoader implements ResourceLoader {
* @param classLoader the ClassLoader to load class path resources with, or {@code null}
* for using the thread context class loader at the time of actual resource access
*/
public DefaultResourceLoader(ClassLoader classLoader) {
public DefaultResourceLoader(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader;
}
@@ -78,7 +79,7 @@ public class DefaultResourceLoader implements ResourceLoader {
* <p>The default is that ClassLoader access will happen using the thread context
* class loader at the time of this ResourceLoader's initialization.
*/
public void setClassLoader(ClassLoader classLoader) {
public void setClassLoader(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader;
}

View File

@@ -16,6 +16,8 @@
package org.springframework.core.io;
import org.springframework.lang.Nullable;
/**
* A resolution strategy for protocol-specific resource handles.
*
@@ -38,6 +40,7 @@ public interface ProtocolResolver {
* @return a corresponding {@code Resource} handle if the given location
* matches this resolver's protocol, or {@code null} otherwise
*/
@Nullable
Resource resolve(String location, ResourceLoader resourceLoader);
}

View File

@@ -24,6 +24,8 @@ import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import org.springframework.lang.Nullable;
/**
* Interface for a resource descriptor that abstracts from the actual
* type of underlying resource, such as a file or class path resource.
@@ -159,6 +161,7 @@ public interface Resource extends InputStreamSource {
* <p>Returns {@code null} if this type of resource does not
* have a filename.
*/
@Nullable
String getFilename();
/**

View File

@@ -21,6 +21,7 @@ import java.io.IOException;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -120,6 +121,7 @@ public class ResourceEditor extends PropertyEditorSupport {
@Override
@Nullable
public String getAsText() {
Resource value = (Resource) getValue();
try {

View File

@@ -16,6 +16,7 @@
package org.springframework.core.io;
import org.springframework.lang.Nullable;
import org.springframework.util.ResourceUtils;
/**
@@ -74,6 +75,7 @@ public interface ResourceLoader {
* ClassLoader isn't accessible)
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
@Nullable
ClassLoader getClassLoader();
}

View File

@@ -1,4 +1,7 @@
/**
* Generic abstraction for working with byte buffer implementations.
*/
@NonNullApi
package org.springframework.core.io.buffer;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Generic abstraction for (file-based) resources, used throughout the framework.
*/
@NonNullApi
package org.springframework.core.io;
import org.springframework.lang.NonNullApi;

View File

@@ -24,6 +24,7 @@ import java.nio.charset.Charset;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -99,6 +100,7 @@ public class EncodedResource implements InputStreamSource {
* Return the encoding to use for reading from the {@linkplain #getResource() resource},
* or {@code null} if none specified.
*/
@Nullable
public final String getEncoding() {
return this.encoding;
}
@@ -107,6 +109,7 @@ public class EncodedResource implements InputStreamSource {
* Return the {@code Charset} to use for reading from the {@linkplain #getResource() resource},
* or {@code null} if none specified.
*/
@Nullable
public final Charset getCharset() {
return this.charset;
}

View File

@@ -21,6 +21,7 @@ import java.util.Locale;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -86,7 +87,7 @@ public class LocalizedResourceHelper {
* @return the most specific localized resource found
* @see java.util.ResourceBundle
*/
public Resource findLocalizedResource(String name, String extension, Locale locale) {
public Resource findLocalizedResource(String name, String extension, @Nullable Locale locale) {
Assert.notNull(name, "Name must not be null");
Assert.notNull(extension, "Extension must not be null");

View File

@@ -44,6 +44,7 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.VfsResource;
import org.springframework.lang.Nullable;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -229,7 +230,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
* at the time of actual resource access
* @see org.springframework.core.io.DefaultResourceLoader
*/
public PathMatchingResourcePatternResolver(ClassLoader classLoader) {
public PathMatchingResourcePatternResolver(@Nullable ClassLoader classLoader) {
this.resourceLoader = new DefaultResourceLoader(classLoader);
}
@@ -817,6 +818,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (Object.class == method.getDeclaringClass()) {

View File

@@ -25,6 +25,7 @@ import java.util.Enumeration;
import java.util.Properties;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.DefaultPropertiesPersister;
@@ -168,7 +169,7 @@ public abstract class PropertiesLoaderUtils {
* @return the populated Properties instance
* @throws IOException if loading failed
*/
public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException {
public static Properties loadAllProperties(String resourceName, @Nullable ClassLoader classLoader) throws IOException {
Assert.notNull(resourceName, "Resource name must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {

View File

@@ -17,6 +17,7 @@
package org.springframework.core.io.support;
import org.springframework.core.io.ResourceLoader;
import org.springframework.lang.Nullable;
import org.springframework.util.ResourceUtils;
/**
@@ -57,7 +58,7 @@ public abstract class ResourcePatternUtils {
* @return the ResourcePatternResolver
* @see PathMatchingResourcePatternResolver
*/
public static ResourcePatternResolver getResourcePatternResolver(ResourceLoader resourceLoader) {
public static ResourcePatternResolver getResourcePatternResolver(@Nullable ResourceLoader resourceLoader) {
if (resourceLoader instanceof ResourcePatternResolver) {
return (ResourcePatternResolver) resourceLoader;
}

View File

@@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.io.UrlResource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
@@ -85,7 +86,7 @@ public abstract class SpringFactoriesLoader {
* @throws IllegalArgumentException if any factory implementation class cannot
* be loaded or if an error occurs while instantiating any factory
*/
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryClass, "'factoryClass' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
@@ -113,7 +114,7 @@ public abstract class SpringFactoriesLoader {
* @see #loadFactories
* @throws IllegalArgumentException if an error occurs while loading factory names
*/
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

View File

@@ -2,4 +2,7 @@
* Support classes for Spring's resource abstraction.
* Includes a ResourcePatternResolver mechanism.
*/
@NonNullApi
package org.springframework.core.io.support;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Provides basic classes for exception handling and version detection,
* and other core helpers that are not specific to any part of the framework.
*/
@NonNullApi
package org.springframework.core;
import org.springframework.lang.NonNullApi;

View File

@@ -3,4 +3,7 @@
* Provides an abstraction over various serialization techniques.
* Includes exceptions for serialization and deserialization failures.
*/
@NonNullApi
package org.springframework.core.serializer;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Support classes for Spring's serializer abstraction.
* Includes adapters to the Converter SPI.
*/
@NonNullApi
package org.springframework.core.serializer.support;
import org.springframework.lang.NonNullApi;

View File

@@ -16,6 +16,8 @@
package org.springframework.core.style;
import org.springframework.lang.Nullable;
/**
* Strategy that encapsulates value String styling algorithms
* according to Spring conventions.
@@ -30,6 +32,6 @@ public interface ValueStyler {
* @param value the Object value to style
* @return the styled String
*/
String style(Object value);
String style(@Nullable Object value);
}

View File

@@ -1,4 +1,7 @@
/**
* Support for styling values as Strings, with ToStringCreator as central class.
*/
@NonNullApi
package org.springframework.core.style;
import org.springframework.lang.NonNullApi;

View File

@@ -22,6 +22,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrencyThrottleSupport;
import org.springframework.util.CustomizableThreadCreator;
@@ -107,6 +108,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator implement
/**
* Return the external factory to use for creating new Threads, if any.
*/
@Nullable
public final ThreadFactory getThreadFactory() {
return this.threadFactory;
}

View File

@@ -2,4 +2,7 @@
* This package defines Spring's core TaskExecutor abstraction,
* and provides SyncTaskExecutor and SimpleAsyncTaskExecutor implementations.
*/
@NonNullApi
package org.springframework.core.task;
import org.springframework.lang.NonNullApi;

View File

@@ -26,6 +26,7 @@ import java.util.concurrent.RejectedExecutionException;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.TaskDecorator;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
@@ -167,7 +168,7 @@ public class TaskExecutorAdapter implements AsyncListenableTaskExecutor {
* @throws RejectedExecutionException if the given runnable cannot be accepted
* @since 4.3
*/
protected void doExecute(Executor concurrentExecutor, TaskDecorator taskDecorator, Runnable runnable)
protected void doExecute(Executor concurrentExecutor, @Nullable TaskDecorator taskDecorator, Runnable runnable)
throws RejectedExecutionException{
concurrentExecutor.execute(taskDecorator != null ? taskDecorator.decorate(runnable) : runnable);

View File

@@ -2,4 +2,7 @@
* Support classes for Spring's TaskExecutor abstraction.
* Includes an adapter for the standard ExecutorService interface.
*/
@NonNullApi
package org.springframework.core.task.support;
import org.springframework.lang.NonNullApi;

View File

@@ -18,6 +18,7 @@ package org.springframework.core.type;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
/**
@@ -58,6 +59,7 @@ public interface AnnotatedTypeMetadata {
* and the defined attribute value as Map value. This return value will be
* {@code null} if no matching annotation is defined.
*/
@Nullable
Map<String, Object> getAnnotationAttributes(String annotationName);
/**
@@ -73,6 +75,7 @@ public interface AnnotatedTypeMetadata {
* and the defined attribute value as Map value. This return value will be
* {@code null} if no matching annotation is defined.
*/
@Nullable
Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);
/**
@@ -86,6 +89,7 @@ public interface AnnotatedTypeMetadata {
* be {@code null} if no matching annotation is defined.
* @see #getAllAnnotationAttributes(String, boolean)
*/
@Nullable
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);
/**
@@ -100,6 +104,7 @@ public interface AnnotatedTypeMetadata {
* be {@code null} if no matching annotation is defined.
* @see #getAllAnnotationAttributes(String)
*/
@Nullable
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
}

View File

@@ -16,6 +16,8 @@
package org.springframework.core.type;
import org.springframework.lang.Nullable;
/**
* Interface that defines abstract metadata of a specific class,
* in a form that does not require that class to be loaded yet.
@@ -81,6 +83,7 @@ public interface ClassMetadata {
* Return the name of the enclosing class of the underlying class,
* or {@code null} if the underlying class is a top-level class.
*/
@Nullable
String getEnclosingClassName();
/**
@@ -92,6 +95,7 @@ public interface ClassMetadata {
* Return the name of the super class of the underlying class,
* or {@code null} if there is no super class defined.
*/
@Nullable
String getSuperClassName();
/**

View File

@@ -26,6 +26,7 @@ import java.util.Set;
import org.springframework.asm.Type;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.ObjectUtils;
@@ -119,6 +120,7 @@ abstract class AnnotationReadingVisitorUtils {
* matching annotation is present in the {@code attributesMap}
* @since 4.0.3
*/
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(
LinkedMultiValueMap<String, AnnotationAttributes> attributesMap,
Map<String, Set<String>> metaAnnotationMap, String annotationName) {

View File

@@ -1,4 +1,7 @@
/**
* Support classes for reading annotation and class-level metadata.
*/
@NonNullApi
package org.springframework.core.type.classreading;
import org.springframework.lang.NonNullApi;

View File

@@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.lang.Nullable;
/**
* Type filter that is aware of traversing over hierarchy.
@@ -140,6 +141,7 @@ public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilte
/**
* Override this to match on super type name.
*/
@Nullable
protected Boolean matchSuperClass(String superClassName) {
return null;
}
@@ -147,6 +149,7 @@ public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilte
/**
* Override this to match on interface type name.
*/
@Nullable
protected Boolean matchInterface(String interfaceName) {
return null;
}

View File

@@ -22,6 +22,7 @@ import java.lang.annotation.Inherited;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -102,6 +103,7 @@ public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter
return hasAnnotation(interfaceName);
}
@Nullable
protected Boolean hasAnnotation(String typeName) {
if (Object.class.getName().equals(typeName)) {
return false;

View File

@@ -16,6 +16,7 @@
package org.springframework.core.type.filter;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -63,6 +64,7 @@ public class AssignableTypeFilter extends AbstractTypeHierarchyTraversingFilter
return matchTargetType(interfaceName);
}
@Nullable
protected Boolean matchTargetType(String typeName) {
if (this.targetType.getName().equals(typeName)) {
return true;

View File

@@ -1,4 +1,7 @@
/**
* Core support package for type filtering (e.g. for classpath scanning).
*/
@NonNullApi
package org.springframework.core.type.filter;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Core support package for type introspection.
*/
@NonNullApi
package org.springframework.core.type;
import org.springframework.lang.NonNullApi;

View File

@@ -0,0 +1,29 @@
package org.springframework.lang;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
/**
* Leverage JSR 305 meta-annotations to define that parameters and return values are
* non-nullable by default.
*
* Should be used at package level in association with {@link Nullable} parameters and
* return values level annotations.
*
* @author Sebastien Deleuze
* @since 5.0
* @see javax.annotation.Nonnull
*/
@Documented
@Nonnull
@Target(ElementType.PACKAGE)
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface NonNullApi {
}

View File

@@ -0,0 +1,28 @@
package org.springframework.lang;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.meta.TypeQualifierDefault;
/**
* Leverage JSR 305 meta-annotations to define the annotated element could be null
* under some circumstances.
*
* Should be used at parameters and return values level in association with
* {@link NonNullApi} package level annotations.
*
* @author Sebastien Deleuze
* @since 5.0
* @see javax.annotation.Nullable
*/
@Documented
@javax.annotation.Nullable
@Target({ElementType.METHOD, ElementType.PARAMETER})
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Nullable {
}

View File

@@ -2,4 +2,6 @@
* Annotations indicating the use of core Java/JDK API beyond the API level of JDK 6 update 18.
* Used descriptively within the framework codebase; validated by Animal Sniffer at build time.
*/
@NonNullApi
package org.springframework.lang;

View File

@@ -20,6 +20,8 @@ import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;
import org.springframework.lang.Nullable;
/**
* Assertion utility class that assists in validating arguments.
*
@@ -148,7 +150,7 @@ public abstract class Assert {
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object is not {@code null}
*/
public static void isNull(Object object, String message) {
public static void isNull(@Nullable Object object, String message) {
if (object != null) {
throw new IllegalArgumentException(message);
}
@@ -165,7 +167,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the object is not {@code null}
* @since 5.0
*/
public static void isNull(Object object, Supplier<String> messageSupplier) {
public static void isNull(@Nullable Object object, Supplier<String> messageSupplier) {
if (object != null) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
}
@@ -175,7 +177,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #isNull(Object, String)}
*/
@Deprecated
public static void isNull(Object object) {
public static void isNull(@Nullable Object object) {
isNull(object, "[Assertion failed] - the object argument must be null");
}
@@ -186,7 +188,7 @@ public abstract class Assert {
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object is {@code null}
*/
public static void notNull(Object object, String message) {
public static void notNull(@Nullable Object object, String message) {
if (object == null) {
throw new IllegalArgumentException(message);
}
@@ -203,7 +205,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the object is {@code null}
* @since 5.0
*/
public static void notNull(Object object, Supplier<String> messageSupplier) {
public static void notNull(@Nullable Object object, Supplier<String> messageSupplier) {
if (object == null) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
}
@@ -213,7 +215,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #notNull(Object, String)}
*/
@Deprecated
public static void notNull(Object object) {
public static void notNull(@Nullable Object object) {
notNull(object, "[Assertion failed] - this argument is required; it must not be null");
}
@@ -226,7 +228,7 @@ public abstract class Assert {
* @see StringUtils#hasLength
* @throws IllegalArgumentException if the text is empty
*/
public static void hasLength(String text, String message) {
public static void hasLength(@Nullable String text, String message) {
if (!StringUtils.hasLength(text)) {
throw new IllegalArgumentException(message);
}
@@ -245,7 +247,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the text is empty
* @since 5.0
*/
public static void hasLength(String text, Supplier<String> messageSupplier) {
public static void hasLength(@Nullable String text, Supplier<String> messageSupplier) {
if (!StringUtils.hasLength(text)) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
}
@@ -255,7 +257,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #hasLength(String, String)}
*/
@Deprecated
public static void hasLength(String text) {
public static void hasLength(@Nullable String text) {
hasLength(text,
"[Assertion failed] - this String argument must have length; it must not be null or empty");
}
@@ -269,7 +271,7 @@ public abstract class Assert {
* @see StringUtils#hasText
* @throws IllegalArgumentException if the text does not contain valid text content
*/
public static void hasText(String text, String message) {
public static void hasText(@Nullable String text, String message) {
if (!StringUtils.hasText(text)) {
throw new IllegalArgumentException(message);
}
@@ -288,7 +290,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the text does not contain valid text content
* @since 5.0
*/
public static void hasText(String text, Supplier<String> messageSupplier) {
public static void hasText(@Nullable String text, Supplier<String> messageSupplier) {
if (!StringUtils.hasText(text)) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
}
@@ -298,7 +300,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #hasText(String, String)}
*/
@Deprecated
public static void hasText(String text) {
public static void hasText(@Nullable String text) {
hasText(text,
"[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
}
@@ -311,7 +313,7 @@ public abstract class Assert {
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the text contains the substring
*/
public static void doesNotContain(String textToSearch, String substring, String message) {
public static void doesNotContain(@Nullable String textToSearch, String substring, String message) {
if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
textToSearch.contains(substring)) {
throw new IllegalArgumentException(message);
@@ -330,7 +332,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the text contains the substring
* @since 5.0
*/
public static void doesNotContain(String textToSearch, String substring, Supplier<String> messageSupplier) {
public static void doesNotContain(@Nullable String textToSearch, String substring, Supplier<String> messageSupplier) {
if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
textToSearch.contains(substring)) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
@@ -341,7 +343,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #doesNotContain(String, String, String)}
*/
@Deprecated
public static void doesNotContain(String textToSearch, String substring) {
public static void doesNotContain(@Nullable String textToSearch, String substring) {
doesNotContain(textToSearch, substring,
() -> "[Assertion failed] - this String argument must not contain the substring [" + substring + "]");
}
@@ -354,7 +356,7 @@ public abstract class Assert {
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object array is {@code null} or contains no elements
*/
public static void notEmpty(Object[] array, String message) {
public static void notEmpty(@Nullable Object[] array, String message) {
if (ObjectUtils.isEmpty(array)) {
throw new IllegalArgumentException(message);
}
@@ -372,7 +374,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the object array is {@code null} or contains no elements
* @since 5.0
*/
public static void notEmpty(Object[] array, Supplier<String> messageSupplier) {
public static void notEmpty(@Nullable Object[] array, Supplier<String> messageSupplier) {
if (ObjectUtils.isEmpty(array)) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
}
@@ -382,7 +384,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #notEmpty(Object[], String)}
*/
@Deprecated
public static void notEmpty(Object[] array) {
public static void notEmpty(@Nullable Object[] array) {
notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
}
@@ -394,7 +396,7 @@ public abstract class Assert {
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object array contains a {@code null} element
*/
public static void noNullElements(Object[] array, String message) {
public static void noNullElements(@Nullable Object[] array, String message) {
if (array != null) {
for (Object element : array) {
if (element == null) {
@@ -416,7 +418,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the object array contains a {@code null} element
* @since 5.0
*/
public static void noNullElements(Object[] array, Supplier<String> messageSupplier) {
public static void noNullElements(@Nullable Object[] array, Supplier<String> messageSupplier) {
if (array != null) {
for (Object element : array) {
if (element == null) {
@@ -430,7 +432,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #noNullElements(Object[], String)}
*/
@Deprecated
public static void noNullElements(Object[] array) {
public static void noNullElements(@Nullable Object[] array) {
noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
}
@@ -443,7 +445,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the collection is {@code null} or
* contains no elements
*/
public static void notEmpty(Collection<?> collection, String message) {
public static void notEmpty(@Nullable Collection<?> collection, String message) {
if (CollectionUtils.isEmpty(collection)) {
throw new IllegalArgumentException(message);
}
@@ -462,7 +464,7 @@ public abstract class Assert {
* contains no elements
* @since 5.0
*/
public static void notEmpty(Collection<?> collection, Supplier<String> messageSupplier) {
public static void notEmpty(@Nullable Collection<?> collection, Supplier<String> messageSupplier) {
if (CollectionUtils.isEmpty(collection)) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
}
@@ -472,7 +474,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #notEmpty(Collection, String)}
*/
@Deprecated
public static void notEmpty(Collection<?> collection) {
public static void notEmpty(@Nullable Collection<?> collection) {
notEmpty(collection,
"[Assertion failed] - this collection must not be empty: it must contain at least 1 element");
}
@@ -485,7 +487,7 @@ public abstract class Assert {
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the map is {@code null} or contains no entries
*/
public static void notEmpty(Map<?, ?> map, String message) {
public static void notEmpty(@Nullable Map<?, ?> map, String message) {
if (CollectionUtils.isEmpty(map)) {
throw new IllegalArgumentException(message);
}
@@ -503,7 +505,7 @@ public abstract class Assert {
* @throws IllegalArgumentException if the map is {@code null} or contains no entries
* @since 5.0
*/
public static void notEmpty(Map<?, ?> map, Supplier<String> messageSupplier) {
public static void notEmpty(@Nullable Map<?, ?> map, Supplier<String> messageSupplier) {
if (CollectionUtils.isEmpty(map)) {
throw new IllegalArgumentException(nullSafeGet(messageSupplier));
}
@@ -513,7 +515,7 @@ public abstract class Assert {
* @deprecated as of 4.3.7, in favor of {@link #notEmpty(Map, String)}
*/
@Deprecated
public static void notEmpty(Map<?, ?> map) {
public static void notEmpty(@Nullable Map<?, ?> map) {
notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
}

View File

@@ -20,6 +20,8 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.springframework.lang.Nullable;
/**
* A simple utility class for Base64 encoding and decoding.
*
@@ -42,7 +44,8 @@ public abstract class Base64Utils {
* @throws IllegalStateException if Base64 encoding between byte arrays is not
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
*/
public static byte[] encode(byte[] src) {
@Nullable
public static byte[] encode(@Nullable byte[] src) {
if (src == null || src.length == 0) {
return src;
}
@@ -56,7 +59,8 @@ public abstract class Base64Utils {
* @throws IllegalStateException if Base64 encoding between byte arrays is not
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
*/
public static byte[] decode(byte[] src) {
@Nullable
public static byte[] decode(@Nullable byte[] src) {
if (src == null || src.length == 0) {
return src;
}
@@ -72,7 +76,8 @@ public abstract class Base64Utils {
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
* @since 4.2.4
*/
public static byte[] encodeUrlSafe(byte[] src) {
@Nullable
public static byte[] encodeUrlSafe(@Nullable byte[] src) {
if (src == null || src.length == 0) {
return src;
}
@@ -88,7 +93,8 @@ public abstract class Base64Utils {
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
* @since 4.2.4
*/
public static byte[] decodeUrlSafe(byte[] src) {
@Nullable
public static byte[] decodeUrlSafe(@Nullable byte[] src) {
if (src == null || src.length == 0) {
return src;
}
@@ -101,7 +107,8 @@ public abstract class Base64Utils {
* @return the encoded byte array as a UTF-8 String
* (or {@code null} if the input was {@code null})
*/
public static String encodeToString(byte[] src) {
@Nullable
public static String encodeToString(@Nullable byte[] src) {
if (src == null) {
return null;
}
@@ -116,7 +123,8 @@ public abstract class Base64Utils {
* @param src the encoded UTF-8 String (may be {@code null})
* @return the original byte array (or {@code null} if the input was {@code null})
*/
public static byte[] decodeFromString(String src) {
@Nullable
public static byte[] decodeFromString(@Nullable String src) {
if (src == null) {
return null;
}
@@ -135,7 +143,8 @@ public abstract class Base64Utils {
* @throws IllegalStateException if Base64 encoding between byte arrays is not
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
*/
public static String encodeToUrlSafeString(byte[] src) {
@Nullable
public static String encodeToUrlSafeString(@Nullable byte[] src) {
return new String(encodeUrlSafe(src), DEFAULT_CHARSET);
}
@@ -147,7 +156,8 @@ public abstract class Base64Utils {
* @throws IllegalStateException if Base64 encoding between byte arrays is not
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
*/
public static byte[] decodeFromUrlSafeString(String src) {
@Nullable
public static byte[] decodeFromUrlSafeString(@Nullable String src) {
return decodeUrlSafe(src.getBytes(DEFAULT_CHARSET));
}

View File

@@ -33,6 +33,8 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
/**
* Miscellaneous class utility methods.
* Mainly for internal use within the framework.
@@ -154,6 +156,7 @@ public abstract class ClassUtils {
* @see Thread#getContextClassLoader()
* @see ClassLoader#getSystemClassLoader()
*/
@Nullable
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
@@ -185,6 +188,7 @@ public abstract class ClassUtils {
* @param classLoaderToUse the actual ClassLoader to use for the thread context
* @return the original thread context ClassLoader, or {@code null} if not overridden
*/
@Nullable
public static ClassLoader overrideThreadContextClassLoader(ClassLoader classLoaderToUse) {
Thread currentThread = Thread.currentThread();
ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
@@ -210,7 +214,7 @@ public abstract class ClassUtils {
* @throws LinkageError if the class file could not be loaded
* @see Class#forName(String, boolean, ClassLoader)
*/
public static Class<?> forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError {
public static Class<?> forName(String name, @Nullable ClassLoader classLoader) throws ClassNotFoundException, LinkageError {
Assert.notNull(name, "Name must not be null");
Class<?> clazz = resolvePrimitiveClassName(name);
@@ -279,7 +283,7 @@ public abstract class ClassUtils {
* (that is, the class could not be found or the class file could not be loaded)
* @see #forName(String, ClassLoader)
*/
public static Class<?> resolveClassName(String className, ClassLoader classLoader) throws IllegalArgumentException {
public static Class<?> resolveClassName(String className, @Nullable ClassLoader classLoader) throws IllegalArgumentException {
try {
return forName(className, classLoader);
}
@@ -302,6 +306,7 @@ public abstract class ClassUtils {
* @return the primitive class, or {@code null} if the name does not denote
* a primitive class or primitive array class
*/
@Nullable
public static Class<?> resolvePrimitiveClassName(String name) {
Class<?> result = null;
// Most class names will be quite long, considering that they
@@ -322,7 +327,7 @@ public abstract class ClassUtils {
* (may be {@code null}, which indicates the default class loader)
* @return whether the specified class is present
*/
public static boolean isPresent(String className, ClassLoader classLoader) {
public static boolean isPresent(String className, @Nullable ClassLoader classLoader) {
try {
forName(className, classLoader);
return true;
@@ -502,7 +507,7 @@ public abstract class ClassUtils {
* @return the qualified name of the method
* @since 4.3.4
*/
public static String getQualifiedMethodName(Method method, Class<?> clazz) {
public static String getQualifiedMethodName(Method method, @Nullable Class<?> clazz) {
Assert.notNull(method, "Method must not be null");
return (clazz != null ? clazz : method.getDeclaringClass()).getName() + '.' + method.getName();
}
@@ -568,6 +573,7 @@ public abstract class ClassUtils {
* @return the constructor, or {@code null} if not found
* @see Class#getConstructor
*/
@Nullable
public static <T> Constructor<T> getConstructorIfAvailable(Class<T> clazz, Class<?>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
try {
@@ -605,7 +611,7 @@ public abstract class ClassUtils {
* @throws IllegalStateException if the method has not been found
* @see Class#getMethod
*/
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) {
public static Method getMethod(Class<?> clazz, String methodName, @Nullable Class<?>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(methodName, "Method name must not be null");
if (paramTypes != null) {
@@ -649,7 +655,8 @@ public abstract class ClassUtils {
* @return the method, or {@code null} if not found
* @see Class#getMethod
*/
public static Method getMethodIfAvailable(Class<?> clazz, String methodName, Class<?>... paramTypes) {
@Nullable
public static Method getMethodIfAvailable(Class<?> clazz, String methodName, @Nullable Class<?>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(methodName, "Method name must not be null");
if (paramTypes != null) {
@@ -748,7 +755,8 @@ public abstract class ClassUtils {
* @return the specific target method, or the original method if the
* {@code targetClass} doesn't implement it or is {@code null}
*/
public static Method getMostSpecificMethod(Method method, Class<?> targetClass) {
@Nullable
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
if (method != null && isOverridable(method, targetClass) &&
targetClass != null && targetClass != method.getDeclaringClass()) {
try {
@@ -816,6 +824,7 @@ public abstract class ClassUtils {
* @return the static method, or {@code null} if no static method was found
* @throws IllegalArgumentException if the method name is blank or the clazz is null
*/
@Nullable
public static Method getStaticMethod(Class<?> clazz, String methodName, Class<?>... args) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(methodName, "Method name must not be null");
@@ -987,7 +996,7 @@ public abstract class ClassUtils {
* @see ClassLoader#getResource
* @see Class#getResource
*/
public static String classPackageAsResourcePath(Class<?> clazz) {
public static String classPackageAsResourcePath(@Nullable Class<?> clazz) {
if (clazz == null) {
return "";
}
@@ -1009,7 +1018,7 @@ public abstract class ClassUtils {
* @return a String of form "[com.foo.Bar, com.foo.Baz]"
* @see java.util.AbstractCollection#toString()
*/
public static String classNamesToString(Class<?>... classes) {
public static String classNamesToString(@Nullable Class<?>... classes) {
return classNamesToString(Arrays.asList(classes));
}
@@ -1022,7 +1031,7 @@ public abstract class ClassUtils {
* @return a String of form "[com.foo.Bar, com.foo.Baz]"
* @see java.util.AbstractCollection#toString()
*/
public static String classNamesToString(Collection<Class<?>> classes) {
public static String classNamesToString(@Nullable Collection<Class<?>> classes) {
if (CollectionUtils.isEmpty(classes)) {
return "[]";
}
@@ -1045,7 +1054,8 @@ public abstract class ClassUtils {
* @return the Class array ({@code null} if the passed-in
* Collection was {@code null})
*/
public static Class<?>[] toClassArray(Collection<Class<?>> collection) {
@Nullable
public static Class<?>[] toClassArray(@Nullable Collection<Class<?>> collection) {
if (collection == null) {
return null;
}
@@ -1083,7 +1093,7 @@ public abstract class ClassUtils {
* (may be {@code null} when accepting all declared interfaces)
* @return all interfaces that the given object implements as an array
*/
public static Class<?>[] getAllInterfacesForClass(Class<?> clazz, ClassLoader classLoader) {
public static Class<?>[] getAllInterfacesForClass(Class<?> clazz, @Nullable ClassLoader classLoader) {
Set<Class<?>> ifcs = getAllInterfacesForClassAsSet(clazz, classLoader);
return ifcs.toArray(new Class<?>[ifcs.size()]);
}
@@ -1119,7 +1129,7 @@ public abstract class ClassUtils {
* (may be {@code null} when accepting all declared interfaces)
* @return all interfaces that the given object implements as a Set
*/
public static Set<Class<?>> getAllInterfacesForClassAsSet(Class<?> clazz, ClassLoader classLoader) {
public static Set<Class<?>> getAllInterfacesForClassAsSet(Class<?> clazz, @Nullable ClassLoader classLoader) {
Assert.notNull(clazz, "Class must not be null");
if (clazz.isInterface() && isVisible(clazz, classLoader)) {
return Collections.<Class<?>>singleton(clazz);
@@ -1159,6 +1169,7 @@ public abstract class ClassUtils {
* given classes is {@code null}, the other class will be returned.
* @since 3.2.6
*/
@Nullable
public static Class<?> determineCommonAncestor(Class<?> clazz1, Class<?> clazz2) {
if (clazz1 == null) {
return clazz2;
@@ -1189,7 +1200,7 @@ public abstract class ClassUtils {
* @param classLoader the ClassLoader to check against (may be {@code null},
* in which case this method will always return {@code true})
*/
public static boolean isVisible(Class<?> clazz, ClassLoader classLoader) {
public static boolean isVisible(Class<?> clazz, @Nullable ClassLoader classLoader) {
if (classLoader == null) {
return true;
}

View File

@@ -30,6 +30,8 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.lang.Nullable;
/**
* Miscellaneous collection utility methods.
* Mainly for internal use within the framework.
@@ -47,7 +49,7 @@ public abstract class CollectionUtils {
* @param collection the Collection to check
* @return whether the given Collection is empty
*/
public static boolean isEmpty(Collection<?> collection) {
public static boolean isEmpty(@Nullable Collection<?> collection) {
return (collection == null || collection.isEmpty());
}
@@ -57,7 +59,7 @@ public abstract class CollectionUtils {
* @param map the Map to check
* @return whether the given Map is empty
*/
public static boolean isEmpty(Map<?, ?> map) {
public static boolean isEmpty(@Nullable Map<?, ?> map) {
return (map == null || map.isEmpty());
}
@@ -74,7 +76,7 @@ public abstract class CollectionUtils {
* @see Arrays#asList(Object[])
*/
@SuppressWarnings("rawtypes")
public static List arrayToList(Object source) {
public static List arrayToList(@Nullable Object source) {
return Arrays.asList(ObjectUtils.toObjectArray(source));
}
@@ -84,7 +86,7 @@ public abstract class CollectionUtils {
* @param collection the target Collection to merge the array into
*/
@SuppressWarnings("unchecked")
public static <E> void mergeArrayIntoCollection(Object array, Collection<E> collection) {
public static <E> void mergeArrayIntoCollection(@Nullable Object array, Collection<E> collection) {
if (collection == null) {
throw new IllegalArgumentException("Collection must not be null");
}
@@ -103,7 +105,7 @@ public abstract class CollectionUtils {
* @param map the target Map to merge the properties into
*/
@SuppressWarnings("unchecked")
public static <K, V> void mergePropertiesIntoMap(Properties props, Map<K, V> map) {
public static <K, V> void mergePropertiesIntoMap(@Nullable Properties props, Map<K, V> map) {
if (map == null) {
throw new IllegalArgumentException("Map must not be null");
}
@@ -205,6 +207,7 @@ public abstract class CollectionUtils {
* @return the first present object, or {@code null} if not found
*/
@SuppressWarnings("unchecked")
@Nullable
public static <E> E findFirstMatch(Collection<?> source, Collection<E> candidates) {
if (isEmpty(source) || isEmpty(candidates)) {
return null;
@@ -225,6 +228,7 @@ public abstract class CollectionUtils {
* or {@code null} if none or more than one such value found
*/
@SuppressWarnings("unchecked")
@Nullable
public static <T> T findValueOfType(Collection<?> collection, Class<T> type) {
if (isEmpty(collection)) {
return null;
@@ -251,6 +255,7 @@ public abstract class CollectionUtils {
* @return a value of one of the given types found if there is a clear match,
* or {@code null} if none or more than one such value found
*/
@Nullable
public static Object findValueOfType(Collection<?> collection, Class<?>[] types) {
if (isEmpty(collection) || ObjectUtils.isEmpty(types)) {
return null;
@@ -294,6 +299,7 @@ public abstract class CollectionUtils {
* @return the common element type, or {@code null} if no clear
* common type has been found (or the collection was empty)
*/
@Nullable
public static Class<?> findCommonElementType(Collection<?> collection) {
if (isEmpty(collection)) {
return null;

View File

@@ -33,6 +33,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantLock;
import org.springframework.lang.Nullable;
/**
* A {@link ConcurrentHashMap} that uses {@link ReferenceType#SOFT soft} or
* {@linkplain ReferenceType#WEAK weak} references for both {@code keys} and {@code values}.
@@ -210,7 +212,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @param o the object to hash (may be null)
* @return the resulting hash code
*/
protected int getHash(Object o) {
protected int getHash(@Nullable Object o) {
int hash = o == null ? 0 : o.hashCode();
hash += (hash << 15) ^ 0xffffcd7d;
hash ^= (hash >>> 10);
@@ -242,7 +244,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @param restructure types of restructure allowed during this call
* @return the reference, or {@code null} if not found
*/
protected final Reference<K, V> getReference(Object key, Restructure restructure) {
@Nullable
protected final Reference<K, V> getReference(@Nullable Object key, Restructure restructure) {
int hash = getHash(key);
return getSegmentForHash(hash).getReference(key, hash, restructure);
}
@@ -317,6 +320,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
@Override
@Nullable
public V replace(K key, final V value) {
return doTask(key, new Task<V>(TaskOption.RESTRUCTURE_BEFORE, TaskOption.SKIP_IF_EMPTY) {
@Override
@@ -443,6 +447,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
setReferences(createReferenceArray(this.initialSize));
}
@Nullable
public Reference<K, V> getReference(Object key, int hash, Restructure restructure) {
if (restructure == Restructure.WHEN_NECESSARY) {
restructureIfNecessary(false);
@@ -582,6 +587,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
}
@Nullable
private Reference<K, V> findInChain(Reference<K, V> reference, Object key, int hash) {
while (reference != null) {
if (reference.getHash() == hash) {
@@ -643,6 +649,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* available.
* @return the entry or {@code null}
*/
@Nullable
Entry<K, V> get();
/**
@@ -655,6 +662,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* Returns the next reference in the chain or {@code null}
* @return the next reference of {@code null}
*/
@Nullable
Reference<K, V> getNext();
/**
@@ -745,7 +753,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @return the result of the task
* @see #execute(Reference, Entry)
*/
protected T execute(Reference<K, V> reference, Entry<K, V> entry, Entries entries) {
@Nullable
protected T execute(@Nullable Reference<K, V> reference, @Nullable Entry<K, V> entry, Entries entries) {
return execute(reference, entry);
}
@@ -756,7 +765,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @return the result of the task
* @see #execute(Reference, Entry, Entries)
*/
protected T execute(Reference<K, V> reference, Entry<K, V> entry) {
@Nullable
protected T execute(@Nullable Reference<K, V> reference, @Nullable Entry<K, V> entry) {
return null;
}
}
@@ -933,7 +943,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @param next the next reference in the chain or {@code null}
* @return a new {@link Reference}
*/
public Reference<K, V> createReference(Entry<K, V> entry, int hash, Reference<K, V> next) {
public Reference<K, V> createReference(Entry<K, V> entry, int hash, @Nullable Reference<K, V> next) {
if (ConcurrentReferenceHashMap.this.referenceType == ReferenceType.WEAK) {
return new WeakEntryReference<>(entry, hash, next, this.queue);
}
@@ -948,6 +958,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @return a reference to purge or {@code null}
*/
@SuppressWarnings("unchecked")
@Nullable
public Reference<K, V> pollForPurge() {
return (Reference<K, V>) this.queue.poll();
}

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