Leniently tolerate null bean as aspect instance

Closes gh-35074
This commit is contained in:
Juergen Hoeller 2025-07-07 14:26:19 +02:00
parent ad00aebaa3
commit 3bd96f72a6
3 changed files with 40 additions and 7 deletions

View File

@ -618,28 +618,35 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* @return the invocation result
* @throws Throwable in case of invocation failure
*/
protected Object invokeAdviceMethod(
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
throws Throwable {
protected @Nullable Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable ex) throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
// As above, but in this case we are given the join point.
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
protected @Nullable Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
protected @Nullable Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
Object aspectInstance = this.aspectInstanceFactory.getAspectInstance();
if (aspectInstance.equals(null)) {
// Possibly a NullBean -> simply proceed if necessary.
if (getJoinPoint() instanceof ProceedingJoinPoint pjp) {
return pjp.proceed();
}
return null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
return this.aspectJAdviceMethod.invoke(aspectInstance, actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +

View File

@ -19,6 +19,7 @@ package org.springframework.aop.aspectj.annotation;
import java.io.Serializable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.OrderUtils;
@ -130,7 +131,12 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
Class<?> type = this.beanFactory.getType(this.name);
if (type != null) {
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
try {
return this.beanFactory.getBean(this.name, Ordered.class).getOrder();
}
catch (BeanNotOfRequiredTypeException ex) {
// Not actually implementing Ordered -> possibly a NullBean.
}
}
return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE);
}

View File

@ -364,6 +364,16 @@ class AspectJAutoProxyCreatorTests {
}
}
@Test
void nullAdviceIsSkipped() {
try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ProxyWithNullAdviceConfig.class)) {
@SuppressWarnings("unchecked")
Supplier<String> supplier = context.getBean(Supplier.class);
assertThat(AopUtils.isAopProxy(supplier)).as("AOP proxy").isTrue();
assertThat(supplier.get()).isEqualTo("lambda");
}
}
private ClassPathXmlApplicationContext newContext(String fileSuffix) {
return new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-" + fileSuffix, getClass());
}
@ -627,6 +637,16 @@ class ProxyTargetClassFalseConfig extends AbstractProxyTargetClassConfig {
class ProxyTargetClassTrueConfig extends AbstractProxyTargetClassConfig {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
class ProxyWithNullAdviceConfig extends AbstractProxyTargetClassConfig {
@Override
SupplierAdvice supplierAdvice() {
return null;
}
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
class PerTargetProxyTargetClassTrueConfig {