From 928a3c7184e1e16ead6ce345c63cb4fd327674f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Mon, 13 Jan 2025 20:50:44 +0100 Subject: [PATCH] Specify generic type nullness in spring-beans See gh-34140 --- .../java/org/springframework/beans/BeanUtils.java | 9 +++++---- .../AutowiredAnnotationBeanPostProcessor.java | 12 ++++++------ ...QualifierAnnotationAutowireCandidateResolver.java | 4 ++-- .../beans/factory/aot/AutowiredArguments.java | 6 +++--- .../aot/AutowiredMethodArgumentsResolver.java | 4 ++-- .../aot/BeanDefinitionPropertiesCodeGenerator.java | 12 ++++++------ .../beans/factory/aot/BeanInstanceSupplier.java | 8 ++++---- .../beans/factory/config/BeanDefinitionVisitor.java | 4 ++-- .../factory/config/ServiceLocatorFactoryBean.java | 4 ++-- .../support/AbstractAutowireCapableBeanFactory.java | 6 +++--- .../beans/factory/support/AutowireUtils.java | 4 ++-- .../factory/support/BeanDefinitionValueResolver.java | 4 ++-- .../beans/factory/support/ConstructorResolver.java | 6 +++--- .../factory/support/DefaultListableBeanFactory.java | 10 +++++----- .../factory/xml/AbstractBeanDefinitionParser.java | 3 ++- .../propertyeditors/StringArrayPropertyEditor.java | 4 ++-- .../support/ArgumentConvertingMethodInvoker.java | 9 +++++---- 17 files changed, 56 insertions(+), 53 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java index 9d7af79ac7f..79ca2a297db 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -196,7 +196,7 @@ public abstract class BeanUtils { return ctor.newInstance(); } Class[] parameterTypes = ctor.getParameterTypes(); - Object[] argsWithDefaultValues = new Object[args.length]; + @Nullable Object[] argsWithDefaultValues = new Object[args.length]; for (int i = 0 ; i < args.length; i++) { if (args[i] == null) { Class parameterType = parameterTypes[i]; @@ -654,9 +654,10 @@ public abstract class BeanUtils { * @see ConstructorProperties * @see DefaultParameterNameDiscoverer */ - public static String[] getParameterNames(Constructor ctor) { + @SuppressWarnings("NullAway") // Dataflow analysis limitation + public static @Nullable String[] getParameterNames(Constructor ctor) { ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class); - String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor)); + @Nullable String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor)); Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor); Assert.state(paramNames.length == ctor.getParameterCount(), () -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index db86247f36e..437e6fe58b6 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -812,7 +812,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA return; } Method method = (Method) this.member; - Object[] arguments; + @Nullable Object[] arguments; if (this.cached) { try { arguments = resolveCachedArguments(beanName, this.cachedMethodArguments); @@ -838,20 +838,20 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA } } - private Object @Nullable [] resolveCachedArguments(@Nullable String beanName, Object @Nullable [] cachedMethodArguments) { + private @Nullable Object @Nullable [] resolveCachedArguments(@Nullable String beanName, Object @Nullable [] cachedMethodArguments) { if (cachedMethodArguments == null) { return null; } - Object[] arguments = new Object[cachedMethodArguments.length]; + @Nullable Object[] arguments = new Object[cachedMethodArguments.length]; for (int i = 0; i < arguments.length; i++) { arguments[i] = resolveCachedArgument(beanName, cachedMethodArguments[i]); } return arguments; } - private Object @Nullable [] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) { + private @Nullable Object @Nullable [] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) { int argumentCount = method.getParameterCount(); - Object[] arguments = new Object[argumentCount]; + @Nullable Object[] arguments = new Object[argumentCount]; DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount]; Set autowiredBeanNames = CollectionUtils.newLinkedHashSet(argumentCount); Assert.state(beanFactory != null, "No BeanFactory available"); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java index fd29c8e102a..86fe581d979 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -291,7 +291,7 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa } } - Map attributes = AnnotationUtils.getAnnotationAttributes(annotation); + Map attributes = AnnotationUtils.getAnnotationAttributes(annotation); if (attributes.isEmpty() && qualifier == null) { // If no attributes, the qualifier must be present return false; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredArguments.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredArguments.java index 0f32a8a2acf..fc440681131 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredArguments.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredArguments.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -74,7 +74,7 @@ public interface AutowiredArguments { * Return the arguments as an object array. * @return the arguments as an object array */ - Object[] toArray(); + @Nullable Object[] toArray(); /** * Factory method to create a new {@link AutowiredArguments} instance from @@ -82,7 +82,7 @@ public interface AutowiredArguments { * @param arguments the arguments * @return a new {@link AutowiredArguments} instance */ - static AutowiredArguments of(Object[] arguments) { + static AutowiredArguments of(@Nullable Object[] arguments) { Assert.notNull(arguments, "'arguments' must not be null"); return () -> arguments; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredMethodArgumentsResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredMethodArgumentsResolver.java index 8775f4466fd..62cc5fd5126 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredMethodArgumentsResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredMethodArgumentsResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -162,7 +162,7 @@ public final class AutowiredMethodArgumentsResolver extends AutowiredElementReso Assert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory); AutowireCapableBeanFactory autowireCapableBeanFactory = (AutowireCapableBeanFactory) beanFactory; int argumentCount = method.getParameterCount(); - Object[] arguments = new Object[argumentCount]; + @Nullable Object[] arguments = new Object[argumentCount]; Set autowiredBeanNames = CollectionUtils.newLinkedHashSet(argumentCount); TypeConverter typeConverter = beanFactory.getTypeConverter(); for (int i = 0; i < argumentCount; i++) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java index e412331454b..482e3539726 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -111,7 +111,7 @@ class BeanDefinitionPropertiesCodeGenerator { this.valueCodeGenerator = ValueCodeGenerator.with(allDelegates).scoped(generatedMethods); } - + @SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1128 CodeBlock generateCode(RootBeanDefinition beanDefinition) { CodeBlock.Builder code = CodeBlock.builder(); addStatementForValue(code, beanDefinition, BeanDefinition::getScope, @@ -344,7 +344,7 @@ class BeanDefinitionPropertiesCodeGenerator { } private void addStatementForValue( - CodeBlock.Builder code, BeanDefinition beanDefinition, Function getter, String format) { + CodeBlock.Builder code, BeanDefinition beanDefinition, Function getter, String format) { addStatementForValue(code, beanDefinition, getter, (defaultValue, actualValue) -> !Objects.equals(defaultValue, actualValue), format); @@ -352,14 +352,14 @@ class BeanDefinitionPropertiesCodeGenerator { private void addStatementForValue( CodeBlock.Builder code, BeanDefinition beanDefinition, - Function getter, BiPredicate filter, String format) { + Function getter, BiPredicate filter, String format) { addStatementForValue(code, beanDefinition, getter, filter, format, actualValue -> actualValue); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "NullAway"}) private void addStatementForValue( - CodeBlock.Builder code, BeanDefinition beanDefinition, Function getter, + CodeBlock.Builder code, BeanDefinition beanDefinition, Function getter, BiPredicate filter, String format, Function formatter) { T defaultValue = getter.apply((B) DEFAULT_BEAN_DEFINITION); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java index 733a76c9120..3f642bd0423 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -200,7 +200,7 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impl } else { Executable executable = this.lookup.get(registeredBean); - Object[] arguments = resolveArguments(registeredBean, executable).toArray(); + @Nullable Object[] arguments = resolveArguments(registeredBean, executable).toArray(); return invokeBeanSupplier(executable, () -> (T) instantiate(registeredBean, executable, arguments)); } } @@ -242,7 +242,7 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impl private AutowiredArguments resolveArguments(RegisteredBean registeredBean, Executable executable) { int parameterCount = executable.getParameterCount(); - Object[] resolved = new Object[parameterCount]; + @Nullable Object[] resolved = new Object[parameterCount]; Assert.isTrue(this.shortcutBeanNames == null || this.shortcutBeanNames.length == resolved.length, () -> "'shortcuts' must contain " + resolved.length + " elements"); @@ -341,7 +341,7 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impl } } - private Object instantiate(RegisteredBean registeredBean, Executable executable, Object[] args) { + private Object instantiate(RegisteredBean registeredBean, Executable executable, @Nullable Object[] args) { if (executable instanceof Constructor constructor) { return BeanUtils.instantiateClass(constructor, args); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java index f91bf12c3bc..96c03de1ef9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -220,7 +220,7 @@ public class BeanDefinitionVisitor { return value; } - protected void visitArray(Object[] arrayVal) { + protected void visitArray(@Nullable Object[] arrayVal) { for (int i = 0; i < arrayVal.length; i++) { Object elem = arrayVal[i]; Object newVal = resolveValue(elem); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.java index 78b5b78160b..95ca1024e5e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -311,7 +311,7 @@ public class ServiceLocatorFactoryBean implements FactoryBean, BeanFacto */ protected Exception createServiceLocatorException(Constructor exceptionConstructor, BeansException cause) { Class[] paramTypes = exceptionConstructor.getParameterTypes(); - Object[] args = new Object[paramTypes.length]; + @Nullable Object[] args = new Object[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { if (String.class == paramTypes[i]) { args[i] = cause.getMessage(); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 39fbef3daae..0fcaacd6c1b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -548,7 +548,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */ - protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object @Nullable [] args) + protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object @Nullable [] args) throws BeanCreationException { // Instantiate the bean. @@ -753,7 +753,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac // Fully resolve parameter names and argument values. ConstructorArgumentValues cav = mbd.getConstructorArgumentValues(); Class[] paramTypes = candidate.getParameterTypes(); - String[] paramNames = null; + @Nullable String[] paramNames = null; if (cav.containsNamedArgument()) { ParameterNameDiscoverer pnd = getParameterNameDiscoverer(); if (pnd != null) { @@ -761,7 +761,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } } Set usedValueHolders = CollectionUtils.newHashSet(paramTypes.length); - Object[] args = new Object[paramTypes.length]; + @Nullable Object[] args = new Object[paramTypes.length]; for (int i = 0; i < args.length; i++) { ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue( i, paramTypes[i], (paramNames != null ? paramNames[i] : null), usedValueHolders); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java index 9e79e6e224b..fc038766219 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -173,7 +173,7 @@ abstract class AutowireUtils { * @since 3.2.5 */ public static Class resolveReturnTypeForFactoryMethod( - Method method, Object[] args, @Nullable ClassLoader classLoader) { + Method method, @Nullable Object[] args, @Nullable ClassLoader classLoader) { Assert.notNull(method, "Method must not be null"); Assert.notNull(args, "Argument array must not be null"); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionValueResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionValueResolver.java index 08af87df259..3c91711fcdf 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionValueResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionValueResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -287,7 +287,7 @@ public class BeanDefinitionValueResolver { } else if (value instanceof String[] values) { boolean actuallyResolved = false; - Object[] resolvedValues = new Object[values.length]; + @Nullable Object[] resolvedValues = new Object[values.length]; for (int i = 0; i < values.length; i++) { String originalValue = values[i]; Object resolvedValue = doEvaluate(originalValue); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java index d219fb56f5b..742dbb869b5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -814,7 +814,7 @@ class ConstructorResolver { /** * Resolve the prepared arguments stored in the given bean definition. */ - private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, + private @Nullable Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Executable executable, Object[] argsToResolve) { TypeConverter customConverter = this.beanFactory.getCustomTypeConverter(); @@ -823,7 +823,7 @@ class ConstructorResolver { new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); Class[] paramTypes = executable.getParameterTypes(); - Object[] resolvedArgs = new Object[argsToResolve.length]; + @Nullable Object[] resolvedArgs = new Object[argsToResolve.length]; for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) { Object argValue = argsToResolve[argIndex]; Class paramType = paramTypes[argIndex]; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index e43cd3d1848..5cef0db1e48 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -357,7 +357,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @SuppressWarnings("unchecked") @Override - public T getBean(Class requiredType, Object @Nullable ... args) throws BeansException { + public T getBean(Class requiredType, @Nullable Object @Nullable ... args) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false); if (resolved == null) { @@ -500,7 +500,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto }; } - private @Nullable T resolveBean(ResolvableType requiredType, Object @Nullable [] args, boolean nonUniqueAsNull) { + private @Nullable T resolveBean(ResolvableType requiredType, @Nullable Object @Nullable [] args, boolean nonUniqueAsNull) { NamedBeanHolder namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull); if (namedBean != null) { return namedBean.getBeanInstance(); @@ -1411,7 +1411,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @SuppressWarnings("unchecked") private @Nullable NamedBeanHolder resolveNamedBean( - ResolvableType requiredType, Object @Nullable [] args, boolean nonUniqueAsNull) throws BeansException { + ResolvableType requiredType, @Nullable Object @Nullable [] args, boolean nonUniqueAsNull) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); String[] candidateNames = getBeanNamesForType(requiredType); @@ -1465,7 +1465,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } private @Nullable NamedBeanHolder resolveNamedBean( - String beanName, ResolvableType requiredType, Object @Nullable [] args) throws BeansException { + String beanName, ResolvableType requiredType, @Nullable Object @Nullable [] args) throws BeansException { Object bean = getBean(beanName, null, args); if (bean instanceof NullBean) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/AbstractBeanDefinitionParser.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/AbstractBeanDefinitionParser.java index 8fb760bcd9f..69001365dec 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/AbstractBeanDefinitionParser.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/AbstractBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,6 +58,7 @@ public abstract class AbstractBeanDefinitionParser implements BeanDefinitionPars @Override + @SuppressWarnings("NullAway") // Dataflow analysis limitation public final @Nullable BeanDefinition parse(Element element, ParserContext parserContext) { AbstractBeanDefinition definition = parseInternal(element, parserContext); if (definition != null && !parserContext.isNested()) { diff --git a/spring-beans/src/main/java/org/springframework/beans/propertyeditors/StringArrayPropertyEditor.java b/spring-beans/src/main/java/org/springframework/beans/propertyeditors/StringArrayPropertyEditor.java index 742d6e48e3f..d99b9c277f5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/propertyeditors/StringArrayPropertyEditor.java +++ b/spring-beans/src/main/java/org/springframework/beans/propertyeditors/StringArrayPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -127,7 +127,7 @@ public class StringArrayPropertyEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { - String[] array = StringUtils.delimitedListToStringArray(text, this.separator, this.charsToDelete); + @Nullable String[] array = StringUtils.delimitedListToStringArray(text, this.separator, this.charsToDelete); if (this.emptyArrayAsNull && array.length == 0) { setValue(null); } diff --git a/spring-beans/src/main/java/org/springframework/beans/support/ArgumentConvertingMethodInvoker.java b/spring-beans/src/main/java/org/springframework/beans/support/ArgumentConvertingMethodInvoker.java index bea627e669c..876b7447142 100644 --- a/spring-beans/src/main/java/org/springframework/beans/support/ArgumentConvertingMethodInvoker.java +++ b/spring-beans/src/main/java/org/springframework/beans/support/ArgumentConvertingMethodInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,7 +130,8 @@ public class ArgumentConvertingMethodInvoker extends MethodInvoker { * @param arguments the argument values to match against method parameters * @return a matching method, or {@code null} if none */ - protected @Nullable Method doFindMatchingMethod(Object[] arguments) { + @SuppressWarnings("NullAway") // Dataflow analysis limitation + protected @Nullable Method doFindMatchingMethod(@Nullable Object[] arguments) { TypeConverter converter = getTypeConverter(); if (converter != null) { String targetMethod = getTargetMethod(); @@ -140,14 +141,14 @@ public class ArgumentConvertingMethodInvoker extends MethodInvoker { Assert.state(targetClass != null, "No target class set"); Method[] candidates = ReflectionUtils.getAllDeclaredMethods(targetClass); int minTypeDiffWeight = Integer.MAX_VALUE; - Object[] argumentsToUse = null; + @Nullable Object[] argumentsToUse = null; for (Method candidate : candidates) { if (candidate.getName().equals(targetMethod)) { // Check if the inspected method has the correct number of parameters. int parameterCount = candidate.getParameterCount(); if (parameterCount == argCount) { Class[] paramTypes = candidate.getParameterTypes(); - Object[] convertedArguments = new Object[argCount]; + @Nullable Object[] convertedArguments = new Object[argCount]; boolean match = true; for (int j = 0; j < argCount && match; j++) { // Verify that the supplied argument is assignable to the method parameter.