diff --git a/framework-platform/framework-platform.gradle b/framework-platform/framework-platform.gradle index 17fb413e78c..fde3ae9d7ab 100644 --- a/framework-platform/framework-platform.gradle +++ b/framework-platform/framework-platform.gradle @@ -127,7 +127,7 @@ dependencies { api("org.hibernate.orm:hibernate-core:7.0.3.Final") api("org.hibernate.validator:hibernate-validator:9.0.1.Final") api("org.hsqldb:hsqldb:2.7.4") - api("org.htmlunit:htmlunit:4.10.0") + api("org.htmlunit:htmlunit:4.13.0") api("org.javamoney:moneta:1.4.4") api("org.jboss.logging:jboss-logging:3.6.1.Final") api("org.jruby:jruby:9.4.12.0") @@ -138,8 +138,8 @@ dependencies { api("org.python:jython-standalone:2.7.4") api("org.quartz-scheduler:quartz:2.3.2") api("org.reactivestreams:reactive-streams:1.0.4") - api("org.seleniumhq.selenium:htmlunit3-driver:4.29.0") - api("org.seleniumhq.selenium:selenium-java:4.29.0") + api("org.seleniumhq.selenium:htmlunit3-driver:4.33.0") + api("org.seleniumhq.selenium:selenium-java:4.33.0") api("org.skyscreamer:jsonassert:2.0-rc1") api("org.testng:testng:7.11.0") api("org.webjars:underscorejs:1.8.3") 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 d648112541d..bb75e0f23bb 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 @@ -617,28 +617,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(@Nullable Object[] args) throws Throwable { + protected @Nullable Object invokeAdviceMethodWithGivenArgs(@Nullable Object[] args) throws Throwable { @Nullable 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 [" + diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java index 33d7efd43e7..599ee6d7270 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java @@ -21,6 +21,7 @@ import java.io.Serializable; import org.jspecify.annotations.Nullable; 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; @@ -129,7 +130,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); } diff --git a/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java b/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java index 55cd0f39768..b1399b9e363 100644 --- a/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java +++ b/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java @@ -364,6 +364,16 @@ class AspectJAutoProxyCreatorTests { } } + @Test + void nullAdviceIsSkipped() { + try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ProxyWithNullAdviceConfig.class)) { + @SuppressWarnings("unchecked") + Supplier 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 {