Skip to content

Commit bc5d771

Browse files
committed
Switch to JSpecify annotations
This commit updates the whole Spring Framework codebase to use JSpecify annotations instead of Spring null-safety annotations with JSR 305 semantics. JSpecify provides signficant enhancements such as properly defined specifications, a canonical dependency with no split-package issue, better tooling, better Kotlin integration and the capability to specify generic type, array and varargs element null-safety. Generic type null-safety is not defined by this commit yet and will be specified later. A key difference is that Spring null-safety annotations, following JSR 305 semantics, apply to fields, parameters and return values, while JSpecify annotations apply to type usages. That's why this commit moves nullability annotations closer to the type for fields and return values. See gh-28797
1 parent fcb8aed commit bc5d771

File tree

3,459 files changed

+14118
-22059
lines changed

Some content is hidden

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

3,459 files changed

+14118
-22059
lines changed

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ configure([rootProject] + javaProjects) { project ->
107107
// Previously there could be a split-package issue between JSR250 and JSR305 javax.annotation packages,
108108
// but since 6.0 JSR 250 annotations such as @Resource and @PostConstruct have been replaced by their
109109
// JakartaEE equivalents in the jakarta.annotation package.
110-
//"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/"
110+
//"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/",
111+
"https://jspecify.dev/docs/api/"
111112
] as String[]
112113
}
113114

framework-docs/src/main/kotlin/org/springframework/docs/integration/cache/cachestoreconfigurationcaffeine/CustomCacheConfiguration.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ class CustomCacheConfiguration {
2828
// tag::snippet[]
2929
@Bean
3030
fun cacheManager(): CacheManager {
31-
return CaffeineCacheManager().apply {
32-
cacheNames = listOf("default", "books")
33-
}
31+
return CaffeineCacheManager("default", "books")
3432
}
3533
// end::snippet[]
3634
}

framework-platform/framework-platform.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ dependencies {
131131
api("org.htmlunit:htmlunit:4.6.0")
132132
api("org.javamoney:moneta:1.4.4")
133133
api("org.jruby:jruby:9.4.9.0")
134+
api("org.jspecify:jspecify:1.0.0")
134135
api("org.junit.support:testng-engine:1.0.5")
135136
api("org.mozilla:rhino:1.7.15")
136137
api("org.ogce:xpp3:1.1.6")

gradle/spring-module.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ dependencies {
1313
jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
1414
jmh 'org.openjdk.jmh:jmh-generator-bytecode:1.37'
1515
jmh 'net.sf.jopt-simple:jopt-simple'
16-
errorprone 'com.uber.nullaway:nullaway:0.10.26'
17-
errorprone 'com.google.errorprone:error_prone_core:2.9.0'
16+
errorprone 'com.uber.nullaway:nullaway:0.12.2'
17+
errorprone 'com.google.errorprone:error_prone_core:2.35.1'
1818
}
1919

2020
pluginManager.withPlugin("kotlin") {

integration-tests/src/test/java/org/springframework/aop/framework/autoproxy/AdvisorAutoProxyCreatorIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121

2222
import jakarta.servlet.ServletException;
23+
import org.jspecify.annotations.Nullable;
2324
import org.junit.jupiter.api.Test;
2425

2526
import org.springframework.aop.support.AopUtils;
@@ -31,7 +32,6 @@
3132
import org.springframework.beans.factory.InitializingBean;
3233
import org.springframework.beans.testfixture.beans.ITestBean;
3334
import org.springframework.context.support.ClassPathXmlApplicationContext;
34-
import org.springframework.lang.Nullable;
3535
import org.springframework.transaction.NoTransactionException;
3636
import org.springframework.transaction.interceptor.TransactionInterceptor;
3737
import org.springframework.transaction.testfixture.CallCountingTransactionManager;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import java.lang.reflect.Method;
2020

21-
import org.springframework.lang.Nullable;
21+
import org.jspecify.annotations.Nullable;
2222

2323
/**
2424
* After returning advice is invoked only on normal method return, not if an

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import java.lang.reflect.Method;
2020

21-
import org.springframework.lang.Nullable;
21+
import org.jspecify.annotations.Nullable;
2222

2323
/**
2424
* Advice invoked before a method is invoked. Such advices cannot

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
package org.springframework.aop;
1818

1919
import org.aopalliance.intercept.MethodInvocation;
20-
21-
import org.springframework.lang.Nullable;
20+
import org.jspecify.annotations.Nullable;
2221

2322
/**
2423
* Extension of the AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}
@@ -83,7 +82,6 @@ public interface ProxyMethodInvocation extends MethodInvocation {
8382
* @return the value of the attribute, or {@code null} if not set
8483
* @see #setUserAttribute
8584
*/
86-
@Nullable
87-
Object getUserAttribute(String key);
85+
@Nullable Object getUserAttribute(String key);
8886

8987
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package org.springframework.aop;
1818

19-
import org.springframework.lang.Nullable;
19+
import org.jspecify.annotations.Nullable;
2020

2121
/**
2222
* Minimal interface for exposing the target class behind a proxy.
@@ -36,7 +36,6 @@ public interface TargetClassAware {
3636
* (typically a proxy configuration or an actual proxy).
3737
* @return the target Class, or {@code null} if not known
3838
*/
39-
@Nullable
40-
Class<?> getTargetClass();
39+
@Nullable Class<?> getTargetClass();
4140

4241
}

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package org.springframework.aop;
1818

19-
import org.springframework.lang.Nullable;
19+
import org.jspecify.annotations.Nullable;
2020

2121
/**
2222
* A {@code TargetSource} is used to obtain the current "target" of
@@ -42,8 +42,7 @@ public interface TargetSource extends TargetClassAware {
4242
* @return the type of targets returned by this {@link TargetSource}
4343
*/
4444
@Override
45-
@Nullable
46-
Class<?> getTargetClass();
45+
@Nullable Class<?> getTargetClass();
4746

4847
/**
4948
* Will all calls to {@link #getTarget()} return the same object?
@@ -64,8 +63,7 @@ default boolean isStatic() {
6463
* or {@code null} if there is no actual target instance
6564
* @throws Exception if the target object can't be resolved
6665
*/
67-
@Nullable
68-
Object getTarget() throws Exception;
66+
@Nullable Object getTarget() throws Exception;
6967

7068
/**
7169
* Release the given target object obtained from the

0 commit comments

Comments
 (0)