From 3bd96f72a69e872085eb664ca392f98aa8a9a6db Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 7 Jul 2025 14:26:19 +0200 Subject: [PATCH 1/2] Leniently tolerate null bean as aspect instance Closes gh-35074 --- .../aop/aspectj/AbstractAspectJAdvice.java | 19 ++++++++++++------ .../BeanFactoryAspectInstanceFactory.java | 8 +++++++- .../AspectJAutoProxyCreatorTests.java | 20 +++++++++++++++++++ 3 files changed, 40 insertions(+), 7 deletions(-) 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 4594fb7e028..15af8421702 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 @@ -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 [" + 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 23b4cf88f68..7ce1f8ad394 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 @@ -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); } 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 17713812583..179b5d862f3 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 { From 1051592ae80e7927258a886ffda2bf4f21169216 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 7 Jul 2025 14:36:01 +0200 Subject: [PATCH 2/2] Upgrade to Selenium 4.33 and HtmlUnit 4.13 --- framework-platform/framework-platform.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework-platform/framework-platform.gradle b/framework-platform/framework-platform.gradle index 707aaadc415..da99bc4d168 100644 --- a/framework-platform/framework-platform.gradle +++ b/framework-platform/framework-platform.gradle @@ -129,7 +129,7 @@ dependencies { api("org.hibernate:hibernate-core-jakarta:5.6.15.Final") api("org.hibernate:hibernate-validator:7.0.5.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.jruby:jruby:9.4.12.0") api("org.junit.support:testng-engine:1.0.5") @@ -137,8 +137,8 @@ dependencies { api("org.ogce:xpp3:1.1.6") api("org.python:jython-standalone:2.7.4") api("org.quartz-scheduler:quartz:2.3.2") - 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:1.5.3") api("org.slf4j:slf4j-api:2.0.17") api("org.testng:testng:7.11.0")