Skip to content

Commit 87598f4

Browse files
committed
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
1 parent 2d37c96 commit 87598f4

File tree

1,315 files changed

+4831
-963
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,315 files changed

+4831
-963
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ configure(allprojects) { project ->
177177
}
178178

179179
dependencies {
180+
provided("com.google.code.findbugs:jsr305:3.0.2")
180181
testCompile("junit:junit:${junitVersion}") {
181182
exclude group:'org.hamcrest', module:'hamcrest-core'
182183
}

spring-aop/src/main/java/org/aopalliance/aop/AspectException.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.aopalliance.aop;
1818

19+
import org.springframework.lang.Nullable;
20+
1921
/**
2022
* Superclass for all AOP infrastructure exceptions.
2123
* Unchecked, as such exceptions are fatal and end user
@@ -41,7 +43,7 @@ public AspectException(String message) {
4143
* @param message the exception message
4244
* @param cause the root cause, if any
4345
*/
44-
public AspectException(String message, Throwable cause) {
46+
public AspectException(String message, @Nullable Throwable cause) {
4547
super(message, cause);
4648
}
4749

spring-aop/src/main/java/org/aopalliance/intercept/MethodInterceptor.java

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

1717
package org.aopalliance.intercept;
1818

19+
import org.springframework.lang.Nullable;
20+
1921
/**
2022
* Intercepts calls on an interface on its way to the target. These
2123
* are nested "on top" of the target.
@@ -52,6 +54,7 @@ public interface MethodInterceptor extends Interceptor {
5254
* @throws Throwable if the interceptors or the target object
5355
* throws an exception
5456
*/
57+
@Nullable
5558
Object invoke(MethodInvocation invocation) throws Throwable;
5659

5760
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.lang.reflect.Method;
2020

21+
import org.springframework.lang.Nullable;
22+
2123
/**
2224
* After returning advice is invoked only on normal method return, not if an
2325
* exception is thrown. Such advice can see the return value, but cannot change it.
@@ -39,6 +41,6 @@ public interface AfterReturningAdvice extends AfterAdvice {
3941
* allowed by the method signature. Otherwise the exception
4042
* will be wrapped as a runtime exception.
4143
*/
42-
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
44+
void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
4345

4446
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.lang.reflect.Method;
2020

21+
import org.springframework.lang.Nullable;
22+
2123
/**
2224
* A specialized type of {@link MethodMatcher} that takes into account introductions
2325
* when matching methods. If there are no introductions on the target class,
@@ -39,6 +41,6 @@ public interface IntroductionAwareMethodMatcher extends MethodMatcher {
3941
* asking is the subject on one or more introductions; {@code false} otherwise
4042
* @return whether or not this method matches statically
4143
*/
42-
boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);
44+
boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions);
4345

4446
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.lang.reflect.Method;
2020

21+
import org.springframework.lang.Nullable;
22+
2123
/**
2224
* Advice invoked before a method is invoked. Such advices cannot
2325
* prevent the method call proceeding, unless they throw a Throwable.
@@ -39,6 +41,6 @@ public interface MethodBeforeAdvice extends BeforeAdvice {
3941
* allowed by the method signature. Otherwise the exception
4042
* will be wrapped as a runtime exception.
4143
*/
42-
void before(Method method, Object[] args, Object target) throws Throwable;
44+
void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
4345

4446
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.lang.reflect.Method;
2020

21+
import org.springframework.lang.Nullable;
22+
2123
/**
2224
* Part of a {@link Pointcut}: Checks whether the target method is eligible for advice.
2325
*
@@ -57,7 +59,7 @@ public interface MethodMatcher {
5759
* the candidate class must be taken to be the method's declaring class)
5860
* @return whether or not this method matches statically
5961
*/
60-
boolean matches(Method method, Class<?> targetClass);
62+
boolean matches(Method method, @Nullable Class<?> targetClass);
6163

6264
/**
6365
* Is this MethodMatcher dynamic, that is, must a final call be made on the
@@ -86,7 +88,7 @@ public interface MethodMatcher {
8688
* @return whether there's a runtime match
8789
* @see MethodMatcher#matches(Method, Class)
8890
*/
89-
boolean matches(Method method, Class<?> targetClass, Object... args);
91+
boolean matches(Method method, @Nullable Class<?> targetClass, Object... args);
9092

9193

9294
/**

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import org.aopalliance.intercept.MethodInvocation;
2020

21+
import org.springframework.lang.Nullable;
22+
2123
/**
2224
* Extension of the AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}
2325
* interface, allowing access to the proxy that the method invocation was made through.
@@ -73,14 +75,15 @@ public interface ProxyMethodInvocation extends MethodInvocation {
7375
* @param key the name of the attribute
7476
* @param value the value of the attribute, or {@code null} to reset it
7577
*/
76-
void setUserAttribute(String key, Object value);
78+
void setUserAttribute(String key, @Nullable Object value);
7779

7880
/**
7981
* Return the value of the specified user attribute.
8082
* @param key the name of the attribute
8183
* @return the value of the attribute, or {@code null} if not set
8284
* @see #setUserAttribute
8385
*/
86+
@Nullable
8487
Object getUserAttribute(String key);
8588

8689
}

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

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

1717
package org.springframework.aop;
1818

19+
import org.springframework.lang.Nullable;
20+
1921
/**
2022
* Minimal interface for exposing the target class behind a proxy.
2123
*
@@ -34,6 +36,7 @@ public interface TargetClassAware {
3436
* (typically a proxy configuration or an actual proxy).
3537
* @return the target Class, or {@code null} if not known
3638
*/
39+
@Nullable
3740
Class<?> getTargetClass();
3841

3942
}

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

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

1717
package org.springframework.aop;
1818

19+
import org.springframework.lang.Nullable;
20+
1921
/**
2022
* A {@code TargetSource} is used to obtain the current "target" of
2123
* an AOP invocation, which will be invoked via reflection if no around
@@ -58,6 +60,7 @@ public interface TargetSource extends TargetClassAware {
5860
* @return the target object, which contains the joinpoint
5961
* @throws Exception if the target object can't be resolved
6062
*/
63+
@Nullable
6164
Object getTarget() throws Exception;
6265

6366
/**

0 commit comments

Comments
 (0)