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 * @return the invocation result
* @throws Throwable in case of invocation failure * @throws Throwable in case of invocation failure
*/ */
protected Object invokeAdviceMethod( protected @Nullable Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch,
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex) @Nullable Object returnValue, @Nullable Throwable ex) throws Throwable {
throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex)); return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
} }
// As above, but in this case we are given the join point. // 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 { @Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t)); 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; Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) { if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null; 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 { try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod); ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs); return this.aspectJAdviceMethod.invoke(aspectInstance, actualArgs);
} }
catch (IllegalArgumentException ex) { catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" + 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 java.io.Serializable;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.OrderUtils; import org.springframework.core.annotation.OrderUtils;
@ -130,7 +131,12 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
Class<?> type = this.beanFactory.getType(this.name); Class<?> type = this.beanFactory.getType(this.name);
if (type != null) { if (type != null) {
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) { 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); 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) { private ClassPathXmlApplicationContext newContext(String fileSuffix) {
return new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-" + fileSuffix, getClass()); return new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-" + fileSuffix, getClass());
} }
@ -627,6 +637,16 @@ class ProxyTargetClassFalseConfig extends AbstractProxyTargetClassConfig {
class ProxyTargetClassTrueConfig extends AbstractProxyTargetClassConfig { class ProxyTargetClassTrueConfig extends AbstractProxyTargetClassConfig {
} }
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
class ProxyWithNullAdviceConfig extends AbstractProxyTargetClassConfig {
@Override
SupplierAdvice supplierAdvice() {
return null;
}
}
@Configuration @Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) @EnableAspectJAutoProxy(proxyTargetClass = true)
class PerTargetProxyTargetClassTrueConfig { class PerTargetProxyTargetClassTrueConfig {