diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java index 7ffffab8bc..6a297ed9d8 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java @@ -545,14 +545,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence * @param ex the exception thrown by the method execution (may be null) * @return the empty array if there are no arguments */ - @SuppressWarnings("NullAway") - protected Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch, + protected @Nullable Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex) { calculateArgumentBindings(); // AMC start - Object[] adviceInvocationArgs = new Object[this.parameterTypes.length]; + @Nullable Object[] adviceInvocationArgs = new Object[this.parameterTypes.length]; int numBound = 0; if (this.joinPointArgumentIndex != -1) { @@ -571,6 +570,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence for (PointcutParameter parameter : parameterBindings) { String name = parameter.getName(); Integer index = this.argumentBindings.get(name); + Assert.notNull(index, "Index must not be null"); adviceInvocationArgs[index] = parameter.getBinding(); numBound++; } @@ -578,12 +578,14 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence // binding from returning clause if (this.returningName != null) { Integer index = this.argumentBindings.get(this.returningName); + Assert.notNull(index, "Index must not be null"); adviceInvocationArgs[index] = returnValue; numBound++; } // binding from thrown exception if (this.throwingName != null) { Integer index = this.argumentBindings.get(this.throwingName); + Assert.notNull(index, "Index must not be null"); adviceInvocationArgs[index] = ex; numBound++; } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java index 4cb6dd3cb9..ceb10d7f51 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java @@ -84,7 +84,6 @@ public class BeanFactoryAspectJAdvisorsBuilder { * @return the list of {@link org.springframework.aop.Advisor} beans * @see #isEligibleBean */ - @SuppressWarnings("NullAway") public List buildAspectJAdvisors() { List aspectNames = this.aspectBeanNames; @@ -158,6 +157,7 @@ public class BeanFactoryAspectJAdvisorsBuilder { } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); + Assert.notNull(factory, "Factory must not be null"); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java index 12a6a47813..daaf18c695 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java @@ -75,9 +75,11 @@ final class InstantiationModelAwarePointcutAdvisorImpl private @Nullable Advice instantiatedAdvice; - private @Nullable Boolean isBeforeAdvice; + @SuppressWarnings("NullAway.Init") + private Boolean isBeforeAdvice; - private @Nullable Boolean isAfterAdvice; + @SuppressWarnings("NullAway.Init") + private Boolean isAfterAdvice; public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, @@ -192,7 +194,6 @@ final class InstantiationModelAwarePointcutAdvisorImpl } @Override - @SuppressWarnings("NullAway") public boolean isBeforeAdvice() { if (this.isBeforeAdvice == null) { determineAdviceType(); @@ -201,7 +202,6 @@ final class InstantiationModelAwarePointcutAdvisorImpl } @Override - @SuppressWarnings("NullAway") public boolean isAfterAdvice() { if (this.isAfterAdvice == null) { determineAdviceType(); diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java index d5588f8867..ddb1292c48 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java @@ -304,7 +304,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { * @param method the method that was invoked * @param params the parameters used to invoke the method */ - protected void handleError(Throwable ex, Method method, Object... params) throws Exception { + protected void handleError(Throwable ex, Method method, @Nullable Object... params) throws Exception { if (Future.class.isAssignableFrom(method.getReturnType())) { ReflectionUtils.rethrowException(ex); } diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionInterceptor.java index edc54e3d26..d1f5cbefb7 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionInterceptor.java @@ -97,7 +97,6 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple * otherwise. */ @Override - @SuppressWarnings("NullAway") public @Nullable Object invoke(final MethodInvocation invocation) throws Throwable { Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); final Method userMethod = BridgeMethodResolver.getMostSpecificMethod(invocation.getMethod(), targetClass); @@ -116,7 +115,8 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple } } catch (ExecutionException ex) { - handleError(ex.getCause(), userMethod, invocation.getArguments()); + Throwable cause = ex.getCause(); + handleError(cause == null ? ex : cause, userMethod, invocation.getArguments()); } catch (Throwable ex) { handleError(ex, userMethod, invocation.getArguments()); diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.java index 868e4898f5..5b80e745b2 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncUncaughtExceptionHandler.java @@ -18,6 +18,8 @@ package org.springframework.aop.interceptor; import java.lang.reflect.Method; +import org.jspecify.annotations.Nullable; + /** * A strategy for handling uncaught exceptions thrown from asynchronous methods. * @@ -38,6 +40,6 @@ public interface AsyncUncaughtExceptionHandler { * @param method the asynchronous method * @param params the parameters used to invoke the method */ - void handleUncaughtException(Throwable ex, Method method, Object... params); + void handleUncaughtException(Throwable ex, Method method, @Nullable Object... params); } diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleAsyncUncaughtExceptionHandler.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleAsyncUncaughtExceptionHandler.java index d11f0d90d8..ba13786d4c 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleAsyncUncaughtExceptionHandler.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleAsyncUncaughtExceptionHandler.java @@ -20,6 +20,7 @@ import java.lang.reflect.Method; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; /** * A default {@link AsyncUncaughtExceptionHandler} that simply logs the exception. @@ -34,7 +35,8 @@ public class SimpleAsyncUncaughtExceptionHandler implements AsyncUncaughtExcepti @Override - public void handleUncaughtException(Throwable ex, Method method, Object... params) { + @SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1113 + public void handleUncaughtException(Throwable ex, Method method, @Nullable Object... params) { if (logger.isErrorEnabled()) { logger.error("Unexpected exception occurred invoking async method: " + method, ex); } diff --git a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java index d2081dfc61..ff0adb3eb7 100644 --- a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java +++ b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java @@ -53,7 +53,7 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc @Override - @SuppressWarnings("NullAway") + @SuppressWarnings("NullAway") // Lambda public @Nullable BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { Class beanClass = registeredBean.getBeanClass(); if (beanClass.equals(ScopedProxyFactoryBean.class)) { diff --git a/spring-aop/src/main/java/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java b/spring-aop/src/main/java/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java index 864ecd9fdc..340e5d2545 100644 --- a/spring-aop/src/main/java/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java +++ b/spring-aop/src/main/java/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java @@ -88,7 +88,7 @@ public class AnnotationMatchingPointcut implements Pointcut { * @see AnnotationClassFilter#AnnotationClassFilter(Class, boolean) * @see AnnotationMethodMatcher#AnnotationMethodMatcher(Class, boolean) */ - @SuppressWarnings("NullAway") + @SuppressWarnings("NullAway") // Dataflow analysis limitation public AnnotationMatchingPointcut(@Nullable Class classAnnotationType, @Nullable Class methodAnnotationType, boolean checkInherited) { diff --git a/spring-aop/src/main/java/org/springframework/aop/target/dynamic/AbstractRefreshableTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/dynamic/AbstractRefreshableTargetSource.java index 645a5602d6..09844bc846 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/dynamic/AbstractRefreshableTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/dynamic/AbstractRefreshableTargetSource.java @@ -42,7 +42,8 @@ public abstract class AbstractRefreshableTargetSource implements TargetSource, R /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); - protected @Nullable Object targetObject; + @SuppressWarnings("NullAway.Init") + protected Object targetObject; private long refreshCheckDelay = -1; @@ -65,7 +66,6 @@ public abstract class AbstractRefreshableTargetSource implements TargetSource, R @Override - @SuppressWarnings("NullAway") public synchronized Class getTargetClass() { if (this.targetObject == null) { refresh();