diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java index ac32f85e89..4d0750db1b 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java @@ -58,6 +58,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator protected final Log logger = LogFactory.getLog(getClass()); + @Nullable private ConfigurableBeanFactory beanFactory; /** Internally used DefaultListableBeanFactory instances, keyed by bean name. */ @@ -76,6 +77,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator /** * Return the BeanFactory that this TargetSourceCreators runs in. */ + @Nullable protected final BeanFactory getBeanFactory() { return this.beanFactory; } diff --git a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java index 5957514cc7..f6673f63c3 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java @@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aop.TargetSource; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; /** @@ -169,7 +170,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour @Override - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { if (this == other) { return true; } diff --git a/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java index da63c2bb2f..b5e926d937 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java @@ -131,7 +131,7 @@ public final class EmptyTargetSource implements TargetSource, Serializable { } @Override - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { if (this == other) { return true; } diff --git a/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java index 3bf01a6b65..0a25e55c0d 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java @@ -19,6 +19,7 @@ package org.springframework.aop.target; import java.io.Serializable; import org.springframework.aop.TargetSource; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -100,7 +101,7 @@ public class HotSwappableTargetSource implements TargetSource, Serializable { * objects are equal. */ @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { return (this == obj || (obj instanceof HotSwappableTargetSource that && this.target.equals(that.target))); } diff --git a/spring-aop/src/main/java/org/springframework/aop/target/LazyInitTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/LazyInitTargetSource.java index ff0b1d1d9a..33b207bbcb 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/LazyInitTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/LazyInitTargetSource.java @@ -65,7 +65,6 @@ public class LazyInitTargetSource extends AbstractBeanFactoryBasedTargetSource { @Override - @Nullable public synchronized Object getTarget() throws BeansException { if (this.target == null) { this.target = getBeanFactory().getBean(getTargetBeanName()); diff --git a/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java index be36de34cb..9c515858f5 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java @@ -19,6 +19,7 @@ package org.springframework.aop.target; import java.io.Serializable; import org.springframework.aop.TargetSource; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -82,7 +83,7 @@ public class SingletonTargetSource implements TargetSource, Serializable { * targets or the targets are equal. */ @Override - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { if (this == other) { return true; } diff --git a/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java b/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java index 3302315566..9697657b6d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java @@ -88,8 +88,9 @@ abstract class PropertyDescriptorUtils { BasicPropertyDescriptor pd = pdMap.get(propertyName); if (pd != null) { if (setter) { - if (pd.getWriteMethod() == null || - pd.getWriteMethod().getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])) { + Method writedMethod = pd.getWriteMethod(); + if (writedMethod == null || + writedMethod.getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])) { pd.setWriteMethod(method); } else { @@ -97,8 +98,9 @@ abstract class PropertyDescriptorUtils { } } else { - if (pd.getReadMethod() == null || - (pd.getReadMethod().getReturnType() == method.getReturnType() && method.getName().startsWith("is"))) { + Method readMethod = pd.getReadMethod(); + if (readMethod == null || + (readMethod.getReturnType() == method.getReturnType() && method.getName().startsWith("is"))) { pd.setReadMethod(method); } } 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 61c47fda01..5d9ca7a3b3 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 @@ -280,6 +280,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA } @Override + @Nullable public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { Class beanClass = registeredBean.getBeanClass(); String beanName = registeredBean.getBeanName(); @@ -323,10 +324,10 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA checkLookupMethods(beanClass, beanName); // Pick up subclass with fresh lookup method override from above - if (this.beanFactory instanceof AbstractAutowireCapableBeanFactory aacbf) { + if (this.beanFactory instanceof AbstractAutowireCapableBeanFactory aacBeanFactory) { RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName); if (mbd.getFactoryMethodName() == null && mbd.hasBeanClass()) { - return aacbf.getInstantiationStrategy().getActualBeanClass(mbd, beanName, this.beanFactory); + return aacBeanFactory.getInstantiationStrategy().getActualBeanClass(mbd, beanName, aacBeanFactory); } } return beanClass; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java index 28281b6dfc..d3b282df1a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java @@ -157,6 +157,7 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB } @Override + @Nullable public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition(); beanDefinition.resolveDestroyMethodIfNecessary(); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/JakartaAnnotationsRuntimeHints.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/JakartaAnnotationsRuntimeHints.java index 0239d42d7d..6b2f35d255 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/JakartaAnnotationsRuntimeHints.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/JakartaAnnotationsRuntimeHints.java @@ -20,6 +20,7 @@ import java.util.stream.Stream; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; /** @@ -31,7 +32,7 @@ import org.springframework.util.ClassUtils; class JakartaAnnotationsRuntimeHints implements RuntimeHintsRegistrar { @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { if (ClassUtils.isPresent("jakarta.inject.Inject", classLoader)) { Stream.of("jakarta.inject.Inject", "jakarta.inject.Qualifier").forEach(annotationType -> hints.reflection().registerType(ClassUtils.resolveClassName(annotationType, classLoader))); 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 57bc2c2fe5..cc926c37e5 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 @@ -25,6 +25,7 @@ import java.util.Set; import org.springframework.beans.SimpleTypeConverter; import org.springframework.beans.TypeConverter; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.DependencyDescriptor; @@ -240,10 +241,11 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa } } if (targetAnnotation == null) { + BeanFactory beanFactory = getBeanFactory(); // Look for matching annotation on the target class - if (getBeanFactory() != null) { + if (beanFactory != null) { try { - Class beanType = getBeanFactory().getType(bdHolder.getBeanName()); + Class beanType = beanFactory.getType(bdHolder.getBeanName()); if (beanType != null) { targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java index a02f6ab3db..81bd57e6fd 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java @@ -188,7 +188,7 @@ public class ConstructorArgumentValues { * rather than matched multiple times. * @param value the argument value */ - public void addGenericArgumentValue(Object value) { + public void addGenericArgumentValue(@Nullable Object value) { this.genericArgumentValues.add(new ValueHolder(value)); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java index dd696bec2d..a01b8ed036 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java @@ -53,6 +53,7 @@ import org.springframework.beans.factory.xml.XmlReaderContext; import org.springframework.core.io.DescriptiveResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.EncodedResource; +import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -149,8 +150,10 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp private MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(getClass()); + @Nullable private Binding binding; + @Nullable private GroovyBeanDefinitionWrapper currentBeanDefinition; @@ -203,6 +206,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp /** * Return a specified binding for Groovy variables, if any. */ + @Nullable public Binding getBinding() { return this.binding; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionWrapper.java b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionWrapper.java index 6b8e2b601e..e52922da03 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionWrapper.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionWrapper.java @@ -30,6 +30,8 @@ import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; /** @@ -55,35 +57,41 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport { FACTORY_BEAN, FACTORY_METHOD, INIT_METHOD, DESTROY_METHOD, SINGLETON); + @Nullable private String beanName; - private Class clazz; + @Nullable + private final Class clazz; - private Collection constructorArgs; + @Nullable + private final Collection constructorArgs; + @Nullable private AbstractBeanDefinition definition; + @Nullable private BeanWrapper definitionWrapper; + @Nullable private String parentName; - public GroovyBeanDefinitionWrapper(String beanName) { - this.beanName = beanName; + GroovyBeanDefinitionWrapper(String beanName) { + this(beanName, null); } - public GroovyBeanDefinitionWrapper(String beanName, Class clazz) { - this.beanName = beanName; - this.clazz = clazz; + GroovyBeanDefinitionWrapper(@Nullable String beanName, @Nullable Class clazz) { + this(beanName, clazz, null); } - public GroovyBeanDefinitionWrapper(String beanName, Class clazz, Collection constructorArgs) { + GroovyBeanDefinitionWrapper(@Nullable String beanName, Class clazz, @Nullable Collection constructorArgs) { this.beanName = beanName; this.clazz = clazz; this.constructorArgs = constructorArgs; } + @Nullable public String getBeanName() { return this.beanName; } @@ -151,6 +159,7 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport { @Override public Object getProperty(String property) { + Assert.state(this.definitionWrapper != null, "BeanDefinition wrapper not initialized"); if (this.definitionWrapper.isReadableProperty(property)) { return this.definitionWrapper.getPropertyValue(property); } @@ -167,6 +176,7 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport { } else { AbstractBeanDefinition bd = getBeanDefinition(); + Assert.state(this.definitionWrapper != null, "BeanDefinition wrapper not initialized"); if (AUTOWIRE.equals(property)) { if ("byName".equals(newValue)) { bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyDynamicElementReader.java b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyDynamicElementReader.java index 3e714247a7..872431dd8f 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyDynamicElementReader.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyDynamicElementReader.java @@ -31,6 +31,7 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; +import org.springframework.lang.Nullable; /** * Used by GroovyBeanDefinitionReader to read a Spring XML namespace expression @@ -68,6 +69,7 @@ class GroovyDynamicElementReader extends GroovyObjectSupport { @Override + @Nullable public Object invokeMethod(String name, Object obj) { Object[] args = (Object[]) obj; if (name.equals("doCall")) { 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 f549112a24..7e264e411e 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 @@ -1958,6 +1958,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } @Override + @Nullable public String getDependencyName() { return null; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java index 201e3d2718..78f06773a9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java @@ -879,10 +879,12 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess */ @Override public MutablePropertyValues getPropertyValues() { - if (this.propertyValues == null) { - this.propertyValues = new MutablePropertyValues(); + MutablePropertyValues pvs = this.propertyValues; + if (pvs == null) { + pvs = new MutablePropertyValues(); + this.propertyValues = pvs; } - return this.propertyValues; + return pvs; } /** diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java index 0a81aef4e9..57c5533df9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java @@ -340,7 +340,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * (within the entire factory). * @param beanName the name of the bean */ - public boolean isSingletonCurrentlyInCreation(String beanName) { + public boolean isSingletonCurrentlyInCreation(@Nullable String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java index 7e7c079266..1374fbc3d7 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java @@ -547,7 +547,8 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { * @see DefaultNamespaceHandlerResolver#DefaultNamespaceHandlerResolver(ClassLoader) */ protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { - ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + ResourceLoader resourceLoader = getResourceLoader(); + ClassLoader cl = (resourceLoader != null ? resourceLoader.getClassLoader() : getBeanClassLoader()); return new DefaultNamespaceHandlerResolver(cl); } 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 82e0bf5a77..20dec0c355 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 @@ -111,6 +111,7 @@ public class ArgumentConvertingMethodInvoker extends MethodInvoker { * @see #doFindMatchingMethod */ @Override + @Nullable protected Method findMatchingMethod() { Method matchingMethod = super.findMatchingMethod(); // Second pass: look for method where arguments can be converted to parameter types. diff --git a/spring-context/src/main/java/org/springframework/context/config/SpringConfiguredBeanDefinitionParser.java b/spring-context/src/main/java/org/springframework/context/config/SpringConfiguredBeanDefinitionParser.java index c83eb857bb..eab8fba81a 100644 --- a/spring-context/src/main/java/org/springframework/context/config/SpringConfiguredBeanDefinitionParser.java +++ b/spring-context/src/main/java/org/springframework/context/config/SpringConfiguredBeanDefinitionParser.java @@ -23,6 +23,7 @@ import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.lang.Nullable; /** * {@link BeanDefinitionParser} responsible for parsing the @@ -44,6 +45,7 @@ class SpringConfiguredBeanDefinitionParser implements BeanDefinitionParser { @Override + @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { if (!parserContext.getRegistry().containsBeanDefinition(BEAN_CONFIGURER_ASPECT_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableInterceptorChain.java b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableInterceptorChain.java index 1d3dab6e6f..5d16f12793 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableInterceptorChain.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableInterceptorChain.java @@ -23,6 +23,7 @@ import java.util.concurrent.Future; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.lang.Nullable; import org.springframework.web.context.request.NativeWebRequest; /** @@ -40,6 +41,7 @@ class CallableInterceptorChain { private int preProcessIndex = -1; + @Nullable private volatile Future taskFuture; @@ -66,7 +68,7 @@ class CallableInterceptorChain { } } - public Object applyPostProcess(NativeWebRequest request, Callable task, Object concurrentResult) { + public Object applyPostProcess(NativeWebRequest request, Callable task, @Nullable Object concurrentResult) { Throwable exceptionResult = null; for (int i = this.preProcessIndex; i >= 0; i--) { try { diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java index 22fbc9835f..0cfea08132 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java @@ -19,6 +19,7 @@ package org.springframework.web.context.request.async; import java.util.concurrent.Callable; import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.lang.Nullable; import org.springframework.web.context.request.NativeWebRequest; /** @@ -104,7 +105,7 @@ public interface CallableProcessingInterceptor { * @throws Exception in case of errors */ default void postProcess(NativeWebRequest request, Callable task, - Object concurrentResult) throws Exception { + @Nullable Object concurrentResult) throws Exception { } /** diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResult.java b/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResult.java index 30bb0a9217..cf53df14f9 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResult.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResult.java @@ -48,6 +48,7 @@ import org.springframework.web.context.request.NativeWebRequest; * @author Rossen Stoyanchev * @author Juergen Hoeller * @author Rob Winch + * @author Sam Brannen * @since 3.2 * @param the result type */ @@ -63,14 +64,19 @@ public class DeferredResult { private final Supplier timeoutResult; + @Nullable private Runnable timeoutCallback; + @Nullable private Consumer errorCallback; + @Nullable private Runnable completionCallback; + @Nullable private DeferredResultHandler resultHandler; + @Nullable private volatile Object result = RESULT_NONE; private volatile boolean expired; @@ -340,7 +346,7 @@ public class DeferredResult { @FunctionalInterface public interface DeferredResultHandler { - void handleResult(Object result); + void handleResult(@Nullable Object result); } } diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultInterceptorChain.java b/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultInterceptorChain.java index 3b8d35660e..29a887fa47 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultInterceptorChain.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultInterceptorChain.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.lang.Nullable; import org.springframework.web.context.request.NativeWebRequest; /** @@ -57,8 +58,9 @@ class DeferredResultInterceptorChain { } } + @Nullable public Object applyPostProcess(NativeWebRequest request, DeferredResult deferredResult, - Object concurrentResult) { + @Nullable Object concurrentResult) { try { for (int i = this.preProcessingIndex; i >= 0; i--) { diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultProcessingInterceptor.java b/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultProcessingInterceptor.java index e181636a61..36c2e2517c 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultProcessingInterceptor.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/DeferredResultProcessingInterceptor.java @@ -16,6 +16,7 @@ package org.springframework.web.context.request.async; +import org.springframework.lang.Nullable; import org.springframework.web.context.request.NativeWebRequest; /** @@ -82,7 +83,7 @@ public interface DeferredResultProcessingInterceptor { * @throws Exception in case of errors */ default void postProcess(NativeWebRequest request, DeferredResult deferredResult, - Object concurrentResult) throws Exception { + @Nullable Object concurrentResult) throws Exception { } /** diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java b/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java index 7833f0018e..395dd43719 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java @@ -28,6 +28,7 @@ import jakarta.servlet.AsyncListener; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.web.context.request.ServletWebRequest; @@ -44,10 +45,6 @@ import org.springframework.web.context.request.ServletWebRequest; */ public class StandardServletAsyncWebRequest extends ServletWebRequest implements AsyncWebRequest, AsyncListener { - private Long timeout; - - private AsyncContext asyncContext; - private final AtomicBoolean asyncCompleted = new AtomicBoolean(); private final List timeoutHandlers = new ArrayList<>(); @@ -56,6 +53,12 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements private final List completionHandlers = new ArrayList<>(); + @Nullable + private Long timeout; + + @Nullable + private AsyncContext asyncContext; + /** * Create a new instance for the given request/response pair. diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java b/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java index a7025ae34d..356e74c76f 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java @@ -52,6 +52,7 @@ import org.springframework.web.context.request.async.DeferredResult.DeferredResu * * @author Rossen Stoyanchev * @author Juergen Hoeller + * @author Sam Brannen * @since 3.2 * @see org.springframework.web.context.request.AsyncWebRequestInterceptor * @see org.springframework.web.servlet.AsyncHandlerInterceptor @@ -76,12 +77,15 @@ public final class WebAsyncManager { private static Boolean taskExecutorWarning = true; + @Nullable private AsyncWebRequest asyncWebRequest; private AsyncTaskExecutor taskExecutor = DEFAULT_TASK_EXECUTOR; + @Nullable private volatile Object concurrentResult = RESULT_NONE; + @Nullable private volatile Object[] concurrentResultContext; /* @@ -164,6 +168,7 @@ public final class WebAsyncManager { * concurrent handling. * @see #clearConcurrentResult() */ + @Nullable public Object[] getConcurrentResultContext() { return this.concurrentResultContext; } @@ -377,7 +382,7 @@ public final class WebAsyncManager { return request != null ? request.getRequestURI() : "servlet container"; } - private void setConcurrentResultAndDispatch(Object result) { + private void setConcurrentResultAndDispatch(@Nullable Object result) { synchronized (WebAsyncManager.this) { if (this.concurrentResult != RESULT_NONE) { return; diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncTask.java b/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncTask.java index 3ca91bf7ef..45ebc84135 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncTask.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncTask.java @@ -30,6 +30,7 @@ import org.springframework.web.context.request.NativeWebRequest; * * @author Rossen Stoyanchev * @author Juergen Hoeller + * @author Sam Brannen * @since 3.2 * @param the value type */ @@ -37,11 +38,14 @@ public class WebAsyncTask implements BeanFactoryAware { private final Callable callable; - private Long timeout; + @Nullable + private final Long timeout; - private AsyncTaskExecutor executor; + @Nullable + private final AsyncTaskExecutor executor; - private String executorName; + @Nullable + private final String executorName; private BeanFactory beanFactory; @@ -59,6 +63,9 @@ public class WebAsyncTask implements BeanFactoryAware { public WebAsyncTask(Callable callable) { Assert.notNull(callable, "Callable must not be null"); this.callable = callable; + this.timeout = null; + this.executor = null; + this.executorName = null; } /** @@ -67,8 +74,11 @@ public class WebAsyncTask implements BeanFactoryAware { * @param callable the callable for concurrent handling */ public WebAsyncTask(long timeout, Callable callable) { - this(callable); + Assert.notNull(callable, "Callable must not be null"); + this.callable = callable; this.timeout = timeout; + this.executor = null; + this.executorName = null; } /** @@ -78,10 +88,12 @@ public class WebAsyncTask implements BeanFactoryAware { * @param callable the callable for concurrent handling */ public WebAsyncTask(@Nullable Long timeout, String executorName, Callable callable) { - this(callable); + Assert.notNull(callable, "Callable must not be null"); Assert.notNull(executorName, "Executor name must not be null"); - this.executorName = executorName; + this.callable = callable; this.timeout = timeout; + this.executor = null; + this.executorName = executorName; } /** @@ -91,10 +103,12 @@ public class WebAsyncTask implements BeanFactoryAware { * @param callable the callable for concurrent handling */ public WebAsyncTask(@Nullable Long timeout, AsyncTaskExecutor executor, Callable callable) { - this(callable); + Assert.notNull(callable, "Callable must not be null"); Assert.notNull(executor, "Executor must not be null"); - this.executor = executor; + this.callable = callable; this.timeout = timeout; + this.executor = executor; + this.executorName = null; } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java index d9eca32157..dcda8f1196 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java @@ -21,6 +21,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.web.server.ServerWebExchange; @@ -142,6 +143,7 @@ public class CompositeRequestCondition extends AbstractRequestConditionAn empty {@code CompositeRequestCondition} matches to all requests. */ @Override + @Nullable public CompositeRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (isEmpty()) { return this; diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ConsumesRequestCondition.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ConsumesRequestCondition.java index ea42c2008f..ac438e18b6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ConsumesRequestCondition.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ConsumesRequestCondition.java @@ -194,6 +194,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition