From 3c1ee64b7f05cd359d8ce8e398a75dce4c033ce9 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 13 May 2020 23:33:47 +0200 Subject: [PATCH] Explicit nullability declarations for all AOP Alliance methods Includes consistent declarations in AOP Alliance related Spring AOP code. Closes gh-24117 --- .../intercept/ConstructorInterceptor.java | 3 ++ .../intercept/ConstructorInvocation.java | 3 ++ .../org/aopalliance/intercept/Invocation.java | 3 ++ .../org/aopalliance/intercept/Joinpoint.java | 6 +++ .../intercept/MethodInterceptor.java | 6 ++- .../intercept/MethodInvocation.java | 3 ++ .../aop/aspectj/AspectJAfterAdvice.java | 4 +- .../aspectj/AspectJAfterThrowingAdvice.java | 4 +- .../aop/aspectj/AspectJAroundAdvice.java | 4 +- .../MethodInvocationProceedingJoinPoint.java | 4 +- .../AfterReturningAdviceInterceptor.java | 4 +- .../MethodBeforeAdviceInterceptor.java | 4 +- .../adapter/ThrowsAdviceInterceptor.java | 3 +- .../interceptor/AbstractTraceInterceptor.java | 4 +- .../ConcurrencyThrottleInterceptor.java | 4 +- .../CustomizableTraceInterceptor.java | 6 ++- .../aop/interceptor/DebugInterceptor.java | 5 ++- .../interceptor/ExposeBeanNameAdvisors.java | 5 ++- .../ExposeInvocationInterceptor.java | 2 + .../interceptor/SimpleTraceInterceptor.java | 8 +++- ...erTargetObjectIntroductionInterceptor.java | 3 +- .../DelegatingIntroductionInterceptor.java | 3 +- .../ExposeInvocationInterceptorTests.java | 34 +--------------- .../ExposedInvocationTestBean.java | 40 +++++++++++++++++++ ...ocationCheckExposedInvocationTestBean.java | 32 +++++++++++++++ .../interceptor/JCacheAspectSupport.java | 3 +- .../jcache/interceptor/JCacheInterceptor.java | 7 +++- .../cache/interceptor/CacheAspectSupport.java | 3 +- .../cache/interceptor/CacheInterceptor.java | 7 +++- .../interceptor/CacheOperationInvoker.java | 5 ++- .../event/EventPublicationInterceptor.java | 3 +- .../jndi/JndiObjectFactoryBean.java | 3 +- .../rmi/JndiRmiClientInterceptor.java | 3 +- .../remoting/rmi/RmiClientInterceptor.java | 3 +- .../RemoteInvocationBasedAccessor.java | 5 ++- .../RemoteInvocationTraceInterceptor.java | 4 +- .../MethodValidationInterceptor.java | 21 ++++++---- .../support/OpenSessionInterceptor.java | 3 +- ...stenceExceptionTranslationInterceptor.java | 1 + .../GenericMessageEndpointFactory.java | 3 +- .../interceptor/TransactionAspectSupport.java | 5 ++- .../HttpInvokerClientInterceptor.java | 3 +- 42 files changed, 202 insertions(+), 77 deletions(-) create mode 100644 spring-aop/src/test/java/org/springframework/aop/interceptor/ExposedInvocationTestBean.java create mode 100644 spring-aop/src/test/java/org/springframework/aop/interceptor/InvocationCheckExposedInvocationTestBean.java diff --git a/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInterceptor.java b/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInterceptor.java index 00a42801142..8ac8f65ca3f 100644 --- a/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInterceptor.java +++ b/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInterceptor.java @@ -16,6 +16,8 @@ package org.aopalliance.intercept; +import javax.annotation.Nonnull; + /** * Intercepts the construction of a new object. * @@ -54,6 +56,7 @@ public interface ConstructorInterceptor extends Interceptor { * @throws Throwable if the interceptors or the target object * throws an exception */ + @Nonnull Object construct(ConstructorInvocation invocation) throws Throwable; } diff --git a/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInvocation.java b/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInvocation.java index 867925b0658..72951383e95 100644 --- a/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInvocation.java +++ b/spring-aop/src/main/java/org/aopalliance/intercept/ConstructorInvocation.java @@ -18,6 +18,8 @@ package org.aopalliance.intercept; import java.lang.reflect.Constructor; +import javax.annotation.Nonnull; + /** * Description of an invocation to a constructor, given to an * interceptor upon constructor-call. @@ -36,6 +38,7 @@ public interface ConstructorInvocation extends Invocation { * {@link Joinpoint#getStaticPart()} method (same result). * @return the constructor being called */ + @Nonnull Constructor getConstructor(); } diff --git a/spring-aop/src/main/java/org/aopalliance/intercept/Invocation.java b/spring-aop/src/main/java/org/aopalliance/intercept/Invocation.java index 69db081b1cc..96caaefefe0 100644 --- a/spring-aop/src/main/java/org/aopalliance/intercept/Invocation.java +++ b/spring-aop/src/main/java/org/aopalliance/intercept/Invocation.java @@ -16,6 +16,8 @@ package org.aopalliance.intercept; +import javax.annotation.Nonnull; + /** * This interface represents an invocation in the program. * @@ -32,6 +34,7 @@ public interface Invocation extends Joinpoint { * array to change the arguments. * @return the argument of the invocation */ + @Nonnull Object[] getArguments(); } diff --git a/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java b/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java index 35608787639..780275e9782 100644 --- a/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java +++ b/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java @@ -18,6 +18,9 @@ package org.aopalliance.intercept; import java.lang.reflect.AccessibleObject; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * This interface represents a generic runtime joinpoint (in the AOP * terminology). @@ -46,6 +49,7 @@ public interface Joinpoint { * @return see the children interfaces' proceed definition * @throws Throwable if the joinpoint throws an exception */ + @Nullable Object proceed() throws Throwable; /** @@ -53,6 +57,7 @@ public interface Joinpoint { *

For instance, the target object for an invocation. * @return the object (can be null if the accessible object is static) */ + @Nullable Object getThis(); /** @@ -60,6 +65,7 @@ public interface Joinpoint { *

The static part is an accessible object on which a chain of * interceptors are installed. */ + @Nonnull AccessibleObject getStaticPart(); } diff --git a/spring-aop/src/main/java/org/aopalliance/intercept/MethodInterceptor.java b/spring-aop/src/main/java/org/aopalliance/intercept/MethodInterceptor.java index 3033b8b5fbc..9188e25e1d0 100644 --- a/spring-aop/src/main/java/org/aopalliance/intercept/MethodInterceptor.java +++ b/spring-aop/src/main/java/org/aopalliance/intercept/MethodInterceptor.java @@ -16,6 +16,9 @@ package org.aopalliance.intercept; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Intercepts calls on an interface on its way to the target. These * are nested "on top" of the target. @@ -52,6 +55,7 @@ public interface MethodInterceptor extends Interceptor { * @throws Throwable if the interceptors or the target object * throws an exception */ - Object invoke(MethodInvocation invocation) throws Throwable; + @Nullable + Object invoke(@Nonnull MethodInvocation invocation) throws Throwable; } diff --git a/spring-aop/src/main/java/org/aopalliance/intercept/MethodInvocation.java b/spring-aop/src/main/java/org/aopalliance/intercept/MethodInvocation.java index 3d73f3d12f0..f1f511bea4c 100644 --- a/spring-aop/src/main/java/org/aopalliance/intercept/MethodInvocation.java +++ b/spring-aop/src/main/java/org/aopalliance/intercept/MethodInvocation.java @@ -18,6 +18,8 @@ package org.aopalliance.intercept; import java.lang.reflect.Method; +import javax.annotation.Nonnull; + /** * Description of an invocation to a method, given to an interceptor * upon method-call. @@ -36,6 +38,7 @@ public interface MethodInvocation extends Invocation { * {@link Joinpoint#getStaticPart()} method (same result). * @return the method being called */ + @Nonnull Method getMethod(); } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java index 46ad280a035..a8081b461aa 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2020 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. @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.AfterAdvice; +import org.springframework.lang.Nullable; /** * Spring AOP advice wrapping an AspectJ after advice method. @@ -42,6 +43,7 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java index 7befd24cf7b..953658d66e5 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2020 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. @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.AfterAdvice; +import org.springframework.lang.Nullable; /** * Spring AOP advice wrapping an AspectJ after-throwing advice method. @@ -57,6 +58,7 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice } @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java index 7eec99f42e8..7a7029323d2 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -25,6 +25,7 @@ import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.weaver.tools.JoinPointMatch; import org.springframework.aop.ProxyMethodInvocation; +import org.springframework.lang.Nullable; /** * Spring AOP around advice (MethodInterceptor) that wraps @@ -60,6 +61,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method } @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java index 471647f89cf..5fb4c3c3e95 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -84,11 +84,13 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, } @Override + @Nullable public Object proceed() throws Throwable { return this.methodInvocation.invocableClone().proceed(); } @Override + @Nullable public Object proceed(Object[] arguments) throws Throwable { Assert.notNull(arguments, "Argument array passed to proceed cannot be null"); if (arguments.length != this.methodInvocation.getArguments().length) { diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/adapter/AfterReturningAdviceInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/framework/adapter/AfterReturningAdviceInterceptor.java index 3e58109be18..4ce1c45c87b 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/adapter/AfterReturningAdviceInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/adapter/AfterReturningAdviceInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.AfterAdvice; import org.springframework.aop.AfterReturningAdvice; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -51,6 +52,7 @@ public class AfterReturningAdviceInterceptor implements MethodInterceptor, After @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/adapter/MethodBeforeAdviceInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/framework/adapter/MethodBeforeAdviceInterceptor.java index 420c6203fba..89d341ec297 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/adapter/MethodBeforeAdviceInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/adapter/MethodBeforeAdviceInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.BeforeAdvice; import org.springframework.aop.MethodBeforeAdvice; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -51,6 +52,7 @@ public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeA @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptor.java index 541e3a32110..fcca4f0d3f2 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -107,6 +107,7 @@ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice { @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/AbstractTraceInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/AbstractTraceInterceptor.java index dd02d2d8ef6..892cf5cacc0 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/AbstractTraceInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/AbstractTraceInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aop.support.AopUtils; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * Base {@code MethodInterceptor} implementation for tracing. @@ -151,6 +152,7 @@ public abstract class AbstractTraceInterceptor implements MethodInterceptor, Ser } else { Object target = invocation.getThis(); + Assert.state(target != null, "Target must not be null"); return LogFactory.getLog(getClassForLogging(target)); } } diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/ConcurrencyThrottleInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/ConcurrencyThrottleInterceptor.java index 09e3fa800cd..dd802ce813b 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/ConcurrencyThrottleInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/ConcurrencyThrottleInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2020 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. @@ -21,6 +21,7 @@ import java.io.Serializable; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.springframework.lang.Nullable; import org.springframework.util.ConcurrencyThrottleSupport; /** @@ -48,6 +49,7 @@ public class ConcurrencyThrottleInterceptor extends ConcurrencyThrottleSupport } @Override + @Nullable public Object invoke(MethodInvocation methodInvocation) throws Throwable { beforeAccess(); try { diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/CustomizableTraceInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/CustomizableTraceInterceptor.java index e6008ee001e..a46c85d0d13 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/CustomizableTraceInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/CustomizableTraceInterceptor.java @@ -296,6 +296,8 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor { @Nullable Object returnValue, @Nullable Throwable throwable, long invocationTime) { Matcher matcher = PATTERN.matcher(message); + Object target = methodInvocation.getThis(); + Assert.state(target != null, "Target must not be null"); StringBuffer output = new StringBuffer(); while (matcher.find()) { @@ -304,11 +306,11 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor { matcher.appendReplacement(output, Matcher.quoteReplacement(methodInvocation.getMethod().getName())); } else if (PLACEHOLDER_TARGET_CLASS_NAME.equals(match)) { - String className = getClassForLogging(methodInvocation.getThis()).getName(); + String className = getClassForLogging(target).getName(); matcher.appendReplacement(output, Matcher.quoteReplacement(className)); } else if (PLACEHOLDER_TARGET_CLASS_SHORT_NAME.equals(match)) { - String shortName = ClassUtils.getShortName(getClassForLogging(methodInvocation.getThis())); + String shortName = ClassUtils.getShortName(getClassForLogging(target)); matcher.appendReplacement(output, Matcher.quoteReplacement(shortName)); } else if (PLACEHOLDER_ARGUMENTS.equals(match)) { diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/DebugInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/DebugInterceptor.java index cc773315203..06ea6102909 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/DebugInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/DebugInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2020 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. @@ -18,6 +18,8 @@ package org.springframework.aop.interceptor; import org.aopalliance.intercept.MethodInvocation; +import org.springframework.lang.Nullable; + /** * AOP Alliance {@code MethodInterceptor} that can be introduced in a chain * to display verbose information about intercepted invocations to the logger. @@ -56,6 +58,7 @@ public class DebugInterceptor extends SimpleTraceInterceptor { @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { synchronized (this) { this.count++; diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisors.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisors.java index 351d6940116..7dfb777dee3 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisors.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisors.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -25,6 +25,7 @@ import org.springframework.aop.support.DefaultIntroductionAdvisor; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.aop.support.DelegatingIntroductionInterceptor; import org.springframework.beans.factory.NamedBean; +import org.springframework.lang.Nullable; /** * Convenient methods for creating advisors that may be used when autoproxying beans @@ -110,6 +111,7 @@ public abstract class ExposeBeanNameAdvisors { } @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); @@ -134,6 +136,7 @@ public abstract class ExposeBeanNameAdvisors { } @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeInvocationInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeInvocationInterceptor.java index 6c14533b395..9822374da1a 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeInvocationInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeInvocationInterceptor.java @@ -25,6 +25,7 @@ import org.springframework.aop.Advisor; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.core.NamedThreadLocal; import org.springframework.core.PriorityOrdered; +import org.springframework.lang.Nullable; /** * Interceptor that exposes the current {@link org.aopalliance.intercept.MethodInvocation} @@ -88,6 +89,7 @@ public final class ExposeInvocationInterceptor implements MethodInterceptor, Pri } @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); invocation.set(mi); diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleTraceInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleTraceInterceptor.java index 87d6186d291..f53fd86ed93 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleTraceInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/SimpleTraceInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -19,6 +19,8 @@ package org.springframework.aop.interceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; +import org.springframework.util.Assert; + /** * Simple AOP Alliance {@code MethodInterceptor} that can be introduced * in a chain to display verbose trace information about intercepted method @@ -73,7 +75,9 @@ public class SimpleTraceInterceptor extends AbstractTraceInterceptor { * @return the description */ protected String getInvocationDescription(MethodInvocation invocation) { - String className = invocation.getThis().getClass().getName(); + Object target = invocation.getThis(); + Assert.state(target != null, "Target must not be null"); + String className = target.getClass().getName(); return "method '" + invocation.getMethod().getName() + "' of class [" + className + "]"; } diff --git a/spring-aop/src/main/java/org/springframework/aop/support/DelegatePerTargetObjectIntroductionInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/support/DelegatePerTargetObjectIntroductionInterceptor.java index dd820c57fb7..e55cf0b6d3b 100644 --- a/spring-aop/src/main/java/org/springframework/aop/support/DelegatePerTargetObjectIntroductionInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/support/DelegatePerTargetObjectIntroductionInterceptor.java @@ -114,12 +114,13 @@ public class DelegatePerTargetObjectIntroductionInterceptor extends Introduction * that it is introduced into. This method is never called for * {@link MethodInvocation MethodInvocations} on the introduced interfaces. */ + @Nullable protected Object doProceed(MethodInvocation mi) throws Throwable { // If we get here, just pass the invocation on. return mi.proceed(); } - private Object getIntroductionDelegateFor(Object targetObject) { + private Object getIntroductionDelegateFor(@Nullable Object targetObject) { synchronized (this.delegateMap) { if (this.delegateMap.containsKey(targetObject)) { return this.delegateMap.get(targetObject); diff --git a/spring-aop/src/main/java/org/springframework/aop/support/DelegatingIntroductionInterceptor.java b/spring-aop/src/main/java/org/springframework/aop/support/DelegatingIntroductionInterceptor.java index 3e97f8a8378..c7c5981fd38 100644 --- a/spring-aop/src/main/java/org/springframework/aop/support/DelegatingIntroductionInterceptor.java +++ b/spring-aop/src/main/java/org/springframework/aop/support/DelegatingIntroductionInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -131,6 +131,7 @@ public class DelegatingIntroductionInterceptor extends IntroductionInfoSupport * that it is introduced into. This method is never called for * {@link MethodInvocation MethodInvocations} on the introduced interfaces. */ + @Nullable protected Object doProceed(MethodInvocation mi) throws Throwable { // If we get here, just pass the invocation on. return mi.proceed(); diff --git a/spring-aop/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java b/spring-aop/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java index 40f266f6471..331dc2b8680 100644 --- a/spring-aop/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -16,13 +16,11 @@ package org.springframework.aop.interceptor; -import org.aopalliance.intercept.MethodInvocation; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.beans.testfixture.beans.ITestBean; -import org.springframework.beans.testfixture.beans.TestBean; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifiedResource; @@ -48,33 +46,3 @@ public class ExposeInvocationInterceptorTests { } } - - -abstract class ExposedInvocationTestBean extends TestBean { - - @Override - public String getName() { - MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation(); - assertions(invocation); - return super.getName(); - } - - @Override - public void absquatulate() { - MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation(); - assertions(invocation); - super.absquatulate(); - } - - protected abstract void assertions(MethodInvocation invocation); -} - - -class InvocationCheckExposedInvocationTestBean extends ExposedInvocationTestBean { - - @Override - protected void assertions(MethodInvocation invocation) { - assertThat(invocation.getThis() == this).isTrue(); - assertThat(ITestBean.class.isAssignableFrom(invocation.getMethod().getDeclaringClass())).as("Invocation should be on ITestBean: " + invocation.getMethod()).isTrue(); - } -} diff --git a/spring-aop/src/test/java/org/springframework/aop/interceptor/ExposedInvocationTestBean.java b/spring-aop/src/test/java/org/springframework/aop/interceptor/ExposedInvocationTestBean.java new file mode 100644 index 00000000000..95e8b7d2d39 --- /dev/null +++ b/spring-aop/src/test/java/org/springframework/aop/interceptor/ExposedInvocationTestBean.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2020 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.aop.interceptor; + +import org.aopalliance.intercept.MethodInvocation; + +import org.springframework.beans.testfixture.beans.TestBean; + +abstract class ExposedInvocationTestBean extends TestBean { + + @Override + public String getName() { + MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation(); + assertions(invocation); + return super.getName(); + } + + @Override + public void absquatulate() { + MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation(); + assertions(invocation); + super.absquatulate(); + } + + protected abstract void assertions(MethodInvocation invocation); +} diff --git a/spring-aop/src/test/java/org/springframework/aop/interceptor/InvocationCheckExposedInvocationTestBean.java b/spring-aop/src/test/java/org/springframework/aop/interceptor/InvocationCheckExposedInvocationTestBean.java new file mode 100644 index 00000000000..05fdd00bf1f --- /dev/null +++ b/spring-aop/src/test/java/org/springframework/aop/interceptor/InvocationCheckExposedInvocationTestBean.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2020 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.aop.interceptor; + +import org.aopalliance.intercept.MethodInvocation; + +import org.springframework.beans.testfixture.beans.ITestBean; + +import static org.assertj.core.api.Assertions.assertThat; + +class InvocationCheckExposedInvocationTestBean extends ExposedInvocationTestBean { + + @Override + protected void assertions(MethodInvocation invocation) { + assertThat(invocation.getThis() == this).isTrue(); + assertThat(ITestBean.class.isAssignableFrom(invocation.getMethod().getDeclaringClass())).as("Invocation should be on ITestBean: " + invocation.getMethod()).isTrue(); + } +} diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheAspectSupport.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheAspectSupport.java index 893e4a6b792..1dbf3c8ae6d 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheAspectSupport.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheAspectSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -165,6 +165,7 @@ public class JCacheAspectSupport extends AbstractCacheInvoker implements Initial * @return the result of the invocation * @see CacheOperationInvoker#invoke() */ + @Nullable protected Object invokeOperation(CacheOperationInvoker invoker) { return invoker.invoke(); } diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheInterceptor.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheInterceptor.java index c4835a2c420..81e65d1a1c1 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheInterceptor.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/JCacheInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -27,6 +27,7 @@ import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.CacheOperationInvoker; import org.springframework.cache.interceptor.SimpleCacheErrorHandler; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.function.SingletonSupplier; /** @@ -78,8 +79,10 @@ public class JCacheInterceptor extends JCacheAspectSupport implements MethodInte } }; + Object target = invocation.getThis(); + Assert.state(target != null, "Target must not be null"); try { - return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments()); + return execute(aopAllianceInvoker, target, method, invocation.getArguments()); } catch (CacheOperationInvoker.ThrowableWrapper th) { throw th.getOriginal(); diff --git a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java index bbb6b1b9832..8be59598778 100644 --- a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java +++ b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java @@ -361,6 +361,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker * @return the result of the invocation * @see CacheOperationInvoker#invoke() */ + @Nullable protected Object invokeOperation(CacheOperationInvoker invoker) { return invoker.invoke(); } @@ -445,7 +446,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker } @Nullable - private Object unwrapReturnValue(Object returnValue) { + private Object unwrapReturnValue(@Nullable Object returnValue) { return ObjectUtils.unwrapOptional(returnValue); } diff --git a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java index 74f35500590..2488fa4c54b 100644 --- a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java +++ b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * AOP Alliance MethodInterceptor for declarative cache @@ -57,8 +58,10 @@ public class CacheInterceptor extends CacheAspectSupport implements MethodInterc } }; + Object target = invocation.getThis(); + Assert.state(target != null, "Target must not be null"); try { - return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments()); + return execute(aopAllianceInvoker, target, method, invocation.getArguments()); } catch (CacheOperationInvoker.ThrowableWrapper th) { throw th.getOriginal(); diff --git a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheOperationInvoker.java b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheOperationInvoker.java index 4c401c3703c..cfaab08137b 100644 --- a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheOperationInvoker.java +++ b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheOperationInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2020 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. @@ -16,6 +16,8 @@ package org.springframework.cache.interceptor; +import org.springframework.lang.Nullable; + /** * Abstract the invocation of a cache operation. * @@ -36,6 +38,7 @@ public interface CacheOperationInvoker { * @return the result of the operation * @throws ThrowableWrapper if an error occurred while invoking the operation */ + @Nullable Object invoke() throws ThrowableWrapper; diff --git a/spring-context/src/main/java/org/springframework/context/event/EventPublicationInterceptor.java b/spring-context/src/main/java/org/springframework/context/event/EventPublicationInterceptor.java index 9ff6b45b2c4..ef5c2e6e362 100644 --- a/spring-context/src/main/java/org/springframework/context/event/EventPublicationInterceptor.java +++ b/spring-context/src/main/java/org/springframework/context/event/EventPublicationInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -94,6 +94,7 @@ public class EventPublicationInterceptor @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { Object retVal = invocation.proceed(); diff --git a/spring-context/src/main/java/org/springframework/jndi/JndiObjectFactoryBean.java b/spring-context/src/main/java/org/springframework/jndi/JndiObjectFactoryBean.java index 10f726acb63..9f2d07982d6 100644 --- a/spring-context/src/main/java/org/springframework/jndi/JndiObjectFactoryBean.java +++ b/spring-context/src/main/java/org/springframework/jndi/JndiObjectFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -368,6 +368,7 @@ public class JndiObjectFactoryBean extends JndiObjectLocator } @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { Context ctx = (isEligible(invocation.getMethod()) ? this.jndiTemplate.getContext() : null); try { diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java index a66168d5e9d..163eb97f841 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -268,6 +268,7 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho * @see java.rmi.NoSuchObjectException */ @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { Object stub; try { diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java index 0e92bca953e..8279186a8cc 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2020 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. @@ -255,6 +255,7 @@ public class RmiClientInterceptor extends RemoteInvocationBasedAccessor * @see java.rmi.NoSuchObjectException */ @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { Remote stub = getStub(); try { diff --git a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationBasedAccessor.java b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationBasedAccessor.java index 73ccf35be06..c7f58152c0c 100644 --- a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationBasedAccessor.java +++ b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationBasedAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2020 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. @@ -18,6 +18,8 @@ package org.springframework.remoting.support; import org.aopalliance.intercept.MethodInvocation; +import org.springframework.lang.Nullable; + /** * Abstract base class for remote service accessors that are based * on serialization of {@link RemoteInvocation} objects. @@ -81,6 +83,7 @@ public abstract class RemoteInvocationBasedAccessor extends UrlBasedRemoteAccess * @throws Throwable if the invocation result is an exception * @see RemoteInvocationResult#recreate() */ + @Nullable protected Object recreateRemoteInvocationResult(RemoteInvocationResult result) throws Throwable { return result.recreate(); } diff --git a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationTraceInterceptor.java b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationTraceInterceptor.java index 72e426cb6ae..2d5dc8e3920 100644 --- a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationTraceInterceptor.java +++ b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationTraceInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2020 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. @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; /** @@ -68,6 +69,7 @@ public class RemoteInvocationTraceInterceptor implements MethodInterceptor { @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { Method method = invocation.getMethod(); if (logger.isDebugEnabled()) { diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java index eb28c85d850..dad782da329 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java @@ -33,6 +33,8 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.SmartFactoryBean; import org.springframework.core.BridgeMethodResolver; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.validation.annotation.Validated; @@ -87,7 +89,7 @@ public class MethodValidationInterceptor implements MethodInterceptor { @Override - @SuppressWarnings("unchecked") + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { // Avoid Validator invocation on FactoryBean.getObjectType/isSingleton if (isFactoryBeanMetadataMethod(invocation.getMethod())) { @@ -101,17 +103,18 @@ public class MethodValidationInterceptor implements MethodInterceptor { Method methodToValidate = invocation.getMethod(); Set> result; + Object target = invocation.getThis(); + Assert.state(target != null, "Target must not be null"); + try { - result = execVal.validateParameters( - invocation.getThis(), methodToValidate, invocation.getArguments(), groups); + result = execVal.validateParameters(target, methodToValidate, invocation.getArguments(), groups); } catch (IllegalArgumentException ex) { // Probably a generic type mismatch between interface and impl as reported in SPR-12237 / HV-1011 // Let's try to find the bridged method on the implementation class... methodToValidate = BridgeMethodResolver.findBridgedMethod( - ClassUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass())); - result = execVal.validateParameters( - invocation.getThis(), methodToValidate, invocation.getArguments(), groups); + ClassUtils.getMostSpecificMethod(invocation.getMethod(), target.getClass())); + result = execVal.validateParameters(target, methodToValidate, invocation.getArguments(), groups); } if (!result.isEmpty()) { throw new ConstraintViolationException(result); @@ -119,7 +122,7 @@ public class MethodValidationInterceptor implements MethodInterceptor { Object returnValue = invocation.proceed(); - result = execVal.validateReturnValue(invocation.getThis(), methodToValidate, returnValue, groups); + result = execVal.validateReturnValue(target, methodToValidate, returnValue, groups); if (!result.isEmpty()) { throw new ConstraintViolationException(result); } @@ -158,7 +161,9 @@ public class MethodValidationInterceptor implements MethodInterceptor { protected Class[] determineValidationGroups(MethodInvocation invocation) { Validated validatedAnn = AnnotationUtils.findAnnotation(invocation.getMethod(), Validated.class); if (validatedAnn == null) { - validatedAnn = AnnotationUtils.findAnnotation(invocation.getThis().getClass(), Validated.class); + Object target = invocation.getThis(); + Assert.state(target != null, "Target must not be null"); + validatedAnn = AnnotationUtils.findAnnotation(target.getClass(), Validated.class); } return (validatedAnn != null ? validatedAnn.value() : new Class[0]); } diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInterceptor.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInterceptor.java index 8af9381f3f0..30e6f842b67 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInterceptor.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -78,6 +78,7 @@ public class OpenSessionInterceptor implements MethodInterceptor, InitializingBe @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { SessionFactory sf = getSessionFactory(); Assert.state(sf != null, "No SessionFactory set"); diff --git a/spring-tx/src/main/java/org/springframework/dao/support/PersistenceExceptionTranslationInterceptor.java b/spring-tx/src/main/java/org/springframework/dao/support/PersistenceExceptionTranslationInterceptor.java index 77278743326..f8fdf757272 100644 --- a/spring-tx/src/main/java/org/springframework/dao/support/PersistenceExceptionTranslationInterceptor.java +++ b/spring-tx/src/main/java/org/springframework/dao/support/PersistenceExceptionTranslationInterceptor.java @@ -134,6 +134,7 @@ public class PersistenceExceptionTranslationInterceptor @Override + @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); diff --git a/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java b/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java index af42a2c837c..15cb289dce3 100644 --- a/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java +++ b/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -107,6 +107,7 @@ public class GenericMessageEndpointFactory extends AbstractMessageEndpointFactor private class GenericMessageEndpoint extends AbstractMessageEndpoint implements MethodInterceptor { @Override + @Nullable public Object invoke(MethodInvocation methodInvocation) throws Throwable { Throwable endpointEx = null; boolean applyDeliveryCalls = !hasBeforeDeliveryBeenCalled(); diff --git a/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java b/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java index 8304e61f870..4c9a27ff152 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java +++ b/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java @@ -375,7 +375,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init cleanupTransactionInfo(txInfo); } - if (vavrPresent && VavrDelegate.isVavrTry(retVal)) { + if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) { // Set rollback-only in case of Vavr failure matching our rollback rules... TransactionStatus status = txInfo.getTransactionStatus(); if (status != null && txAttr != null) { @@ -396,7 +396,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status); try { Object retVal = invocation.proceedWithInvocation(); - if (vavrPresent && VavrDelegate.isVavrTry(retVal)) { + if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) { // Set rollback-only in case of Vavr failure matching our rollback rules... retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status); } @@ -780,6 +780,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init @FunctionalInterface protected interface InvocationCallback { + @Nullable Object proceedWithInvocation() throws Throwable; } diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java index 7ca54983d5d..1233c166662 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -142,6 +142,7 @@ public class HttpInvokerClientInterceptor extends RemoteInvocationBasedAccessor @Override + @Nullable public Object invoke(MethodInvocation methodInvocation) throws Throwable { if (AopUtils.isToStringMethod(methodInvocation.getMethod())) { return "HTTP invoker proxy for service URL [" + getServiceUrl() + "]";