Skip to content

Commit 5f6d8df

Browse files
committed
Introduce isLambdaClass() as a public utility in ClassUtils
This commit extracts isLambda() from AopProxyUtils and makes it publicly available as ClassUtils.isLambdaClass(). This is a prerequisite for gh-28209.
1 parent 35de7e1 commit 5f6d8df

File tree

5 files changed

+76
-75
lines changed

5 files changed

+76
-75
lines changed

Diff for: spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java

+1-15
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean deco
134134
if (targetClass.isInterface()) {
135135
advised.setInterfaces(targetClass);
136136
}
137-
else if (Proxy.isProxyClass(targetClass) || isLambda(targetClass)) {
137+
else if (Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
138138
advised.setInterfaces(targetClass.getInterfaces());
139139
}
140140
specifiedInterfaces = advised.getProxiedInterfaces();
@@ -245,18 +245,4 @@ static Object[] adaptArgumentsIfNecessary(Method method, @Nullable Object[] argu
245245
return arguments;
246246
}
247247

248-
/**
249-
* Determine if the supplied {@link Class} is a JVM-generated implementation
250-
* class for a lambda expression or method reference.
251-
* <p>This method makes a best-effort attempt at determining this, based on
252-
* checks that work on modern, main stream JVMs.
253-
* @param clazz the class to check
254-
* @return {@code true} if the class is a lambda implementation class
255-
* @since 5.3.16
256-
*/
257-
static boolean isLambda(Class<?> clazz) {
258-
return (clazz.isSynthetic() && (clazz.getSuperclass() == Object.class) &&
259-
(clazz.getInterfaces().length > 0) && clazz.getName().contains("$$Lambda"));
260-
}
261-
262248
}

Diff for: spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.springframework.aop.SpringProxy;
2323
import org.springframework.core.NativeDetector;
24+
import org.springframework.util.ClassUtils;
2425

2526
/**
2627
* Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy
@@ -60,7 +61,7 @@ public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException
6061
throw new AopConfigException("TargetSource cannot determine target class: " +
6162
"Either an interface or a target is required for proxy creation.");
6263
}
63-
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || AopProxyUtils.isLambda(targetClass)) {
64+
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
6465
return new JdkDynamicAopProxy(config);
6566
}
6667
return new ObjenesisCglibAopProxy(config);

Diff for: spring-aop/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java

-58
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.lang.reflect.Proxy;
2020
import java.util.Arrays;
2121
import java.util.List;
22-
import java.util.function.Supplier;
2322

2423
import org.junit.jupiter.api.Test;
2524

@@ -134,61 +133,4 @@ public void testProxiedUserInterfacesWithNoInterface() {
134133
AopProxyUtils.proxiedUserInterfaces(proxy));
135134
}
136135

137-
@Test
138-
void isLambda() {
139-
assertIsLambda(AopProxyUtilsTests.staticLambdaExpression);
140-
assertIsLambda(AopProxyUtilsTests::staticStringFactory);
141-
142-
assertIsLambda(this.instanceLambdaExpression);
143-
assertIsLambda(this::instanceStringFactory);
144-
}
145-
146-
@Test
147-
void isNotLambda() {
148-
assertIsNotLambda(new EnigmaSupplier());
149-
150-
assertIsNotLambda(new Supplier<String>() {
151-
@Override
152-
public String get() {
153-
return "anonymous inner class";
154-
}
155-
});
156-
157-
assertIsNotLambda(new Fake$$LambdaSupplier());
158-
}
159-
160-
private static void assertIsLambda(Supplier<String> supplier) {
161-
assertThat(AopProxyUtils.isLambda(supplier.getClass())).isTrue();
162-
}
163-
164-
private static void assertIsNotLambda(Supplier<String> supplier) {
165-
assertThat(AopProxyUtils.isLambda(supplier.getClass())).isFalse();
166-
}
167-
168-
private static final Supplier<String> staticLambdaExpression = () -> "static lambda expression";
169-
170-
private final Supplier<String> instanceLambdaExpression = () -> "instance lambda expressions";
171-
172-
private static String staticStringFactory() {
173-
return "static string factory";
174-
}
175-
176-
private String instanceStringFactory() {
177-
return "instance string factory";
178-
}
179-
180-
private static class EnigmaSupplier implements Supplier<String> {
181-
@Override
182-
public String get() {
183-
return "enigma";
184-
}
185-
}
186-
187-
private static class Fake$$LambdaSupplier implements Supplier<String> {
188-
@Override
189-
public String get() {
190-
return "fake lambda";
191-
}
192-
}
193-
194136
}

Diff for: spring-core/src/main/java/org/springframework/util/ClassUtils.java

+14
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,20 @@ public static boolean isInnerClass(Class<?> clazz) {
842842
return (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers()));
843843
}
844844

845+
/**
846+
* Determine if the supplied {@link Class} is a JVM-generated implementation
847+
* class for a lambda expression or method reference.
848+
* <p>This method makes a best-effort attempt at determining this, based on
849+
* checks that work on modern, mainstream JVMs.
850+
* @param clazz the class to check
851+
* @return {@code true} if the class is a lambda implementation class
852+
* @since 5.3.19
853+
*/
854+
public static boolean isLambdaClass(Class<?> clazz) {
855+
return (clazz.isSynthetic() && (clazz.getSuperclass() == Object.class) &&
856+
(clazz.getInterfaces().length > 0) && clazz.getName().contains("$$Lambda"));
857+
}
858+
845859
/**
846860
* Check whether the given object is a CGLIB proxy.
847861
* @param object the object to check

Diff for: spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java

+59-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
3131
import java.util.Collections;
3232
import java.util.List;
3333
import java.util.Set;
34+
import java.util.function.Supplier;
3435

3536
import org.junit.jupiter.api.BeforeEach;
3637
import org.junit.jupiter.api.Nested;
@@ -408,6 +409,29 @@ void isPrimitiveOrWrapperWithWrapper(Class<?> type) {
408409
assertThat(ClassUtils.isPrimitiveOrWrapper(type)).isTrue();
409410
}
410411

412+
@Test
413+
void isLambda() {
414+
assertIsLambda(ClassUtilsTests.staticLambdaExpression);
415+
assertIsLambda(ClassUtilsTests::staticStringFactory);
416+
417+
assertIsLambda(this.instanceLambdaExpression);
418+
assertIsLambda(this::instanceStringFactory);
419+
}
420+
421+
@Test
422+
void isNotLambda() {
423+
assertIsNotLambda(new EnigmaSupplier());
424+
425+
assertIsNotLambda(new Supplier<String>() {
426+
@Override
427+
public String get() {
428+
return "anonymous inner class";
429+
}
430+
});
431+
432+
assertIsNotLambda(new Fake$$LambdaSupplier());
433+
}
434+
411435

412436
@Nested
413437
class GetStaticMethodTests {
@@ -500,4 +524,38 @@ void print(String header, String[] messages, String footer) {
500524
}
501525
}
502526

527+
private static void assertIsLambda(Supplier<String> supplier) {
528+
assertThat(ClassUtils.isLambdaClass(supplier.getClass())).isTrue();
529+
}
530+
531+
private static void assertIsNotLambda(Supplier<String> supplier) {
532+
assertThat(ClassUtils.isLambdaClass(supplier.getClass())).isFalse();
533+
}
534+
535+
private static final Supplier<String> staticLambdaExpression = () -> "static lambda expression";
536+
537+
private final Supplier<String> instanceLambdaExpression = () -> "instance lambda expressions";
538+
539+
private static String staticStringFactory() {
540+
return "static string factory";
541+
}
542+
543+
private String instanceStringFactory() {
544+
return "instance string factory";
545+
}
546+
547+
private static class EnigmaSupplier implements Supplier<String> {
548+
@Override
549+
public String get() {
550+
return "enigma";
551+
}
552+
}
553+
554+
private static class Fake$$LambdaSupplier implements Supplier<String> {
555+
@Override
556+
public String get() {
557+
return "fake lambda";
558+
}
559+
}
560+
503561
}

0 commit comments

Comments
 (0)