Skip to content

Commit 5b660da

Browse files
committed
Perform NullAway build-time checks in more modules
This commit enables null-safety build-time checks in: - spring-jdbc - spring-r2dbc - spring-orm - spring-beans - spring-aop See spring-projectsgh-32475
1 parent 3b4f8db commit 5b660da

File tree

46 files changed

+78
-12
lines changed

Some content is hidden

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

46 files changed

+78
-12
lines changed

gradle/spring-module.gradle

+3-2
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,11 @@ tasks.withType(JavaCompile).configureEach {
118118
disableAllChecks = true
119119
option("NullAway:CustomContractAnnotations", "org.springframework.lang.Contract")
120120
option("NullAway:AnnotatedPackages", "org.springframework.core,org.springframework.expression," +
121-
"org.springframework.web,org.springframework.jms,org.springframework.messaging")
121+
"org.springframework.web,org.springframework.jms,org.springframework.messaging,org.springframework.jdbc," +
122+
"org.springframework.r2dbc,org.springframework.orm,org.springframework.beans,org.springframework.aop")
122123
option("NullAway:UnannotatedSubPackages", "org.springframework.instrument,org.springframework.context.index," +
123124
"org.springframework.asm,org.springframework.cglib,org.springframework.objenesis," +
124-
"org.springframework.javapoet,org.springframework.aot.nativex.substitution")
125+
"org.springframework.javapoet,org.springframework.aot.nativex.substitution,org.springframework.aot.nativex.feature")
125126
}
126127
}
127128
tasks.compileJava {

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

+1
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ private void configurePointcutParameters(String[] argumentNames, int argumentInd
552552
* @param ex the exception thrown by the method execution (may be null)
553553
* @return the empty array if there are no arguments
554554
*/
555+
@SuppressWarnings("NullAway")
555556
protected Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
556557
@Nullable Object returnValue, @Nullable Throwable ex) {
557558

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, @N
7777
this.beanFactory = beanFactory;
7878
this.name = name;
7979
Class<?> resolvedType = type;
80-
if (type == null) {
80+
if (resolvedType == null) {
8181
resolvedType = beanFactory.getType(name);
8282
Assert.notNull(resolvedType, "Unresolvable bean type - explicitly specify the aspect class");
8383
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, Aspect
8080
* @return the list of {@link org.springframework.aop.Advisor} beans
8181
* @see #isEligibleBean
8282
*/
83+
@SuppressWarnings("NullAway")
8384
public List<Advisor> buildAspectJAdvisors() {
8485
List<String> aspectNames = this.aspectBeanNames;
8586

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

+2
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ public int getDeclarationOrder() {
195195
}
196196

197197
@Override
198+
@SuppressWarnings("NullAway")
198199
public boolean isBeforeAdvice() {
199200
if (this.isBeforeAdvice == null) {
200201
determineAdviceType();
@@ -203,6 +204,7 @@ public boolean isBeforeAdvice() {
203204
}
204205

205206
@Override
207+
@SuppressWarnings("NullAway")
206208
public boolean isAfterAdvice() {
207209
if (this.isAfterAdvice == null) {
208210
determineAdviceType();

spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionInterceptor.java

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public AsyncExecutionInterceptor(@Nullable Executor defaultExecutor, AsyncUncaug
9898
*/
9999
@Override
100100
@Nullable
101+
@SuppressWarnings("NullAway")
101102
public Object invoke(final MethodInvocation invocation) throws Throwable {
102103
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
103104
final Method userMethod = BridgeMethodResolver.getMostSpecificMethod(invocation.getMethod(), targetClass);

spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc
5454

5555
@Override
5656
@Nullable
57+
@SuppressWarnings("NullAway")
5758
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
5859
Class<?> beanClass = registeredBean.getBeanClass();
5960
if (beanClass.equals(ScopedProxyFactoryBean.class)) {

spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.beans.factory.support.AbstractBeanDefinition;
2323
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
2424
import org.springframework.beans.factory.support.RootBeanDefinition;
25+
import org.springframework.lang.Contract;
2526
import org.springframework.lang.Nullable;
2627
import org.springframework.util.Assert;
2728

@@ -128,6 +129,7 @@ public static String getOriginalBeanName(@Nullable String targetBeanName) {
128129
* the target bean within a scoped proxy.
129130
* @since 4.1.4
130131
*/
132+
@Contract("null -> false")
131133
public static boolean isScopedTarget(@Nullable String beanName) {
132134
return (beanName != null && beanName.startsWith(TARGET_NAME_PREFIX));
133135
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springframework.core.CoroutinesUtils;
4444
import org.springframework.core.KotlinDetector;
4545
import org.springframework.core.MethodIntrospector;
46+
import org.springframework.lang.Contract;
4647
import org.springframework.lang.Nullable;
4748
import org.springframework.util.Assert;
4849
import org.springframework.util.ClassUtils;
@@ -73,6 +74,7 @@ public abstract class AopUtils {
7374
* @see #isJdkDynamicProxy
7475
* @see #isCglibProxy
7576
*/
77+
@Contract("null -> false")
7678
public static boolean isAopProxy(@Nullable Object object) {
7779
return (object instanceof SpringProxy && (Proxy.isProxyClass(object.getClass()) ||
7880
object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)));
@@ -86,6 +88,7 @@ public static boolean isAopProxy(@Nullable Object object) {
8688
* @param object the object to check
8789
* @see java.lang.reflect.Proxy#isProxyClass
8890
*/
91+
@Contract("null -> false")
8992
public static boolean isJdkDynamicProxy(@Nullable Object object) {
9093
return (object instanceof SpringProxy && Proxy.isProxyClass(object.getClass()));
9194
}
@@ -98,6 +101,7 @@ public static boolean isJdkDynamicProxy(@Nullable Object object) {
98101
* @param object the object to check
99102
* @see ClassUtils#isCglibProxy(Object)
100103
*/
104+
@Contract("null -> false")
101105
public static boolean isCglibProxy(@Nullable Object object) {
102106
return (object instanceof SpringProxy &&
103107
object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR));

spring-aop/src/main/java/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public AnnotationMatchingPointcut(@Nullable Class<? extends Annotation> classAnn
8787
* @see AnnotationClassFilter#AnnotationClassFilter(Class, boolean)
8888
* @see AnnotationMethodMatcher#AnnotationMethodMatcher(Class, boolean)
8989
*/
90+
@SuppressWarnings("NullAway")
9091
public AnnotationMatchingPointcut(@Nullable Class<? extends Annotation> classAnnotationType,
9192
@Nullable Class<? extends Annotation> methodAnnotationType, boolean checkInherited) {
9293

spring-aop/src/main/java/org/springframework/aop/target/dynamic/AbstractRefreshableTargetSource.java

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public void setRefreshCheckDelay(long refreshCheckDelay) {
6666

6767

6868
@Override
69+
@SuppressWarnings("NullAway")
6970
public synchronized Class<?> getTargetClass() {
7071
if (this.targetObject == null) {
7172
refresh();

spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ public GenericTypeAwarePropertyDescriptor(Class<?> beanClass, String propertyNam
106106
// by the JDK's JavaBeans Introspector...
107107
Set<Method> ambiguousCandidates = new HashSet<>();
108108
for (Method method : beanClass.getMethods()) {
109-
if (method.getName().equals(writeMethodToUse.getName()) &&
110-
!method.equals(writeMethodToUse) && !method.isBridge() &&
111-
method.getParameterCount() == writeMethodToUse.getParameterCount()) {
109+
if (method.getName().equals(this.writeMethod.getName()) &&
110+
!method.equals(this.writeMethod) && !method.isBridge() &&
111+
method.getParameterCount() == this.writeMethod.getParameterCount()) {
112112
ambiguousCandidates.add(method);
113113
}
114114
}

spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ public void overrideDefaultEditor(Class<?> requiredType, PropertyEditor property
179179
* @see #registerDefaultEditors
180180
*/
181181
@Nullable
182+
@SuppressWarnings("NullAway")
182183
public PropertyEditor getDefaultEditor(Class<?> requiredType) {
183184
if (!this.defaultEditorsActive) {
184185
return null;

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.beans.MutablePropertyValues;
2929
import org.springframework.beans.PropertyValues;
3030
import org.springframework.beans.factory.support.RootBeanDefinition;
31+
import org.springframework.lang.Contract;
3132
import org.springframework.lang.Nullable;
3233
import org.springframework.util.CollectionUtils;
3334
import org.springframework.util.ReflectionUtils;
@@ -182,6 +183,7 @@ public static InjectionMetadata forElements(Collection<InjectedElement> elements
182183
* @return {@code true} indicating a refresh, {@code false} otherwise
183184
* @see #needsRefresh(Class)
184185
*/
186+
@Contract("null, _ -> true")
185187
public static boolean needsRefresh(@Nullable InjectionMetadata metadata, Class<?> clazz) {
186188
return (metadata == null || metadata.needsRefresh(clazz));
187189
}

spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,9 @@ public boolean equals(@Nullable Object other) {
413413
if (!super.equals(other)) {
414414
return false;
415415
}
416-
DependencyDescriptor otherDesc = (DependencyDescriptor) other;
417-
return (this.required == otherDesc.required && this.eager == otherDesc.eager &&
418-
this.nestingLevel == otherDesc.nestingLevel && this.containingClass == otherDesc.containingClass);
416+
return (other instanceof DependencyDescriptor otherDesc && this.required == otherDesc.required &&
417+
this.eager == otherDesc.eager && this.nestingLevel == otherDesc.nestingLevel &&
418+
this.containingClass == otherDesc.containingClass);
419419
}
420420

421421
@Override

spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java

+1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ public void setBeanClassLoader(ClassLoader classLoader) {
167167

168168

169169
@Override
170+
@SuppressWarnings("NullAway")
170171
public void afterPropertiesSet() throws ClassNotFoundException, NoSuchFieldException {
171172
if (this.targetClass != null && this.targetObject != null) {
172173
throw new IllegalArgumentException("Specify either targetClass or targetObject, not both");

spring-beans/src/main/java/org/springframework/beans/factory/config/PlaceholderConfigurerSupport.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public void setBeanFactory(BeanFactory beanFactory) {
228228
this.beanFactory = beanFactory;
229229
}
230230

231-
231+
@SuppressWarnings("NullAway")
232232
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
233233
StringValueResolver valueResolver) {
234234

spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyPathFactoryBean.java

+1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ public void setBeanName(String beanName) {
162162

163163

164164
@Override
165+
@SuppressWarnings("NullAway")
165166
public void setBeanFactory(BeanFactory beanFactory) {
166167
this.beanFactory = beanFactory;
167168

spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java

+1
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ else if (this.currentBeanDefinition != null) {
701701
}
702702
}
703703

704+
@SuppressWarnings("NullAway")
704705
private GroovyDynamicElementReader createDynamicElementReader(String namespace) {
705706
XmlReaderContext readerContext = this.groovyDslXmlBeanDefinitionReader.createReaderContext(
706707
new DescriptiveResource("Groovy"));

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

+2
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
130130
* or {@code null} if none (-> use constructor argument values from bean definition)
131131
* @return a BeanWrapper for the new instance
132132
*/
133+
@SuppressWarnings("NullAway")
133134
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
134135
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
135136

@@ -391,6 +392,7 @@ private boolean isStaticCandidate(Method method, Class<?> factoryClass) {
391392
* method, or {@code null} if none (-> use constructor argument values from bean definition)
392393
* @return a BeanWrapper for the new instance
393394
*/
395+
@SuppressWarnings("NullAway")
394396
public BeanWrapper instantiateUsingFactoryMethod(
395397
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
396398

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

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
8282
import org.springframework.core.log.LogMessage;
8383
import org.springframework.core.metrics.StartupStep;
84+
import org.springframework.lang.Contract;
8485
import org.springframework.lang.Nullable;
8586
import org.springframework.util.Assert;
8687
import org.springframework.util.ClassUtils;
@@ -1487,6 +1488,7 @@ else if (descriptor.supportsLazyResolution()) {
14871488
}
14881489

14891490
@Nullable
1491+
@SuppressWarnings("NullAway")
14901492
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
14911493
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
14921494

@@ -2066,6 +2068,7 @@ protected boolean matchesBeanName(String beanName, @Nullable String candidateNam
20662068
* i.e. whether the candidate points back to the original bean or to a factory method
20672069
* on the original bean.
20682070
*/
2071+
@Contract("null, _ -> false;_, null -> false;")
20692072
private boolean isSelfReference(@Nullable String beanName, @Nullable String candidateName) {
20702073
return (beanName != null && candidateName != null &&
20712074
(beanName.equals(candidateName) || (containsBeanDefinition(candidateName) &&

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

+1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ protected Object getSingleton(String beanName, boolean allowEarlyReference) {
238238
* with, if necessary
239239
* @return the registered singleton object
240240
*/
241+
@SuppressWarnings("NullAway")
241242
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
242243
Assert.notNull(beanName, "Bean name must not be null");
243244

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

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDesc
7373
* Match the given dependency type with its generic type information against the given
7474
* candidate bean definition.
7575
*/
76+
@SuppressWarnings("NullAway")
7677
protected boolean checkGenericTypeMatch(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
7778
ResolvableType dependencyType = descriptor.getResolvableType();
7879
if (dependencyType.getType() instanceof Class) {

spring-beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java

+1
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
411411
* {@link org.springframework.beans.factory.parsing.ProblemReporter}.
412412
*/
413413
@Nullable
414+
@SuppressWarnings("NullAway")
414415
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
415416
String id = ele.getAttribute(ID_ATTRIBUTE);
416417
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ enum InstrumentedMethod {
187187
/**
188188
* {@link Class#getField(String)}.
189189
*/
190+
@SuppressWarnings("NullAway")
190191
CLASS_GETFIELD(Class.class, "getField", HintType.REFLECTION,
191192
invocation -> {
192193
Field field = invocation.getReturnValue();

spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentTypePreparedStatementSetter.java

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class ArgumentTypePreparedStatementSetter implements PreparedStatementSet
4646
* @param args the arguments to set
4747
* @param argTypes the corresponding SQL types of the arguments
4848
*/
49+
@SuppressWarnings("NullAway")
4950
public ArgumentTypePreparedStatementSetter(@Nullable Object[] args, @Nullable int[] argTypes) {
5051
if ((args != null && argTypes == null) || (args == null && argTypes != null) ||
5152
(args != null && args.length != argTypes.length)) {

spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCall.java

+7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.jdbc.core.RowMapper;
2727
import org.springframework.jdbc.core.SqlParameter;
2828
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
29+
import org.springframework.lang.Nullable;
2930

3031
/**
3132
* A SimpleJdbcCall is a multithreaded, reusable object representing a call
@@ -148,36 +149,42 @@ public SimpleJdbcCall withNamedBinding() {
148149
}
149150

150151
@Override
152+
@Nullable
151153
@SuppressWarnings("unchecked")
152154
public <T> T executeFunction(Class<T> returnType, Object... args) {
153155
return (T) doExecute(args).get(getScalarOutParameterName());
154156
}
155157

156158
@Override
159+
@Nullable
157160
@SuppressWarnings("unchecked")
158161
public <T> T executeFunction(Class<T> returnType, Map<String, ?> args) {
159162
return (T) doExecute(args).get(getScalarOutParameterName());
160163
}
161164

162165
@Override
166+
@Nullable
163167
@SuppressWarnings("unchecked")
164168
public <T> T executeFunction(Class<T> returnType, SqlParameterSource args) {
165169
return (T) doExecute(args).get(getScalarOutParameterName());
166170
}
167171

168172
@Override
173+
@Nullable
169174
@SuppressWarnings("unchecked")
170175
public <T> T executeObject(Class<T> returnType, Object... args) {
171176
return (T) doExecute(args).get(getScalarOutParameterName());
172177
}
173178

174179
@Override
180+
@Nullable
175181
@SuppressWarnings("unchecked")
176182
public <T> T executeObject(Class<T> returnType, Map<String, ?> args) {
177183
return (T) doExecute(args).get(getScalarOutParameterName());
178184
}
179185

180186
@Override
187+
@Nullable
181188
@SuppressWarnings("unchecked")
182189
public <T> T executeObject(Class<T> returnType, SqlParameterSource args) {
183190
return (T) doExecute(args).get(getScalarOutParameterName());

0 commit comments

Comments
 (0)