diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java b/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java index 47bf3deed53..5043c8829e2 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -43,6 +43,7 @@ import org.springframework.util.ObjectUtils; * * @author Rod Johnson * @author Juergen Hoeller + * @author Sam Brannen * @see org.springframework.aop.support.AopUtils */ public abstract class AopProxyUtils { @@ -127,7 +128,7 @@ public abstract class AopProxyUtils { if (targetClass.isInterface()) { advised.setInterfaces(targetClass); } - else if (Proxy.isProxyClass(targetClass)) { + else if (Proxy.isProxyClass(targetClass) || isLambda(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } specifiedInterfaces = advised.getProxiedInterfaces(); @@ -238,4 +239,18 @@ public abstract class AopProxyUtils { return arguments; } + /** + * Determine if the supplied {@link Class} is a JVM-generated implementation + * class for a lambda expression or method reference. + *
This method makes a best-effort attempt at determining this, based on
+ * checks that work on modern, main stream JVMs.
+ * @param clazz the class to check
+ * @return {@code true} if the class is a lambda implementation class
+ * @since 5.2.16
+ */
+ static boolean isLambda(Class> clazz) {
+ return (clazz.isSynthetic() && (clazz.getSuperclass() == Object.class) &&
+ (clazz.getInterfaces().length > 0) && clazz.getName().contains("$$Lambda"));
+ }
+
}
diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java b/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java
index 8692371d3a8..5f1acad9a9a 100644
--- a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java
+++ b/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -40,6 +40,7 @@ import org.springframework.core.NativeDetector;
* @author Rod Johnson
* @author Juergen Hoeller
* @author Sebastien Deleuze
+ * @author Sam Brannen
* @since 12.03.2004
* @see AdvisedSupport#setOptimize
* @see AdvisedSupport#setProxyTargetClass
@@ -59,7 +60,7 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
- if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
+ if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || AopProxyUtils.isLambda(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
diff --git a/spring-aop/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java b/spring-aop/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java
index c8475794f33..3dbf550a121 100644
--- a/spring-aop/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java
+++ b/spring-aop/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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,7 @@ package org.springframework.aop.framework;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;
+import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
@@ -32,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
/**
* @author Rod Johnson
* @author Chris Beams
+ * @author Sam Brannen
*/
public class AopProxyUtilsTests {
@@ -132,4 +134,61 @@ public class AopProxyUtilsTests {
AopProxyUtils.proxiedUserInterfaces(proxy));
}
+ @Test
+ void isLambda() {
+ assertIsLambda(AopProxyUtilsTests.staticLambdaExpression);
+ assertIsLambda(AopProxyUtilsTests::staticStringFactory);
+
+ assertIsLambda(this.instanceLambdaExpression);
+ assertIsLambda(this::instanceStringFactory);
+ }
+
+ @Test
+ void isNotLambda() {
+ assertIsNotLambda(new EnigmaSupplier());
+
+ assertIsNotLambda(new Supplier