mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
Introduce KotlinDetector#hasSerializableAnnotation
This commit introduces a KotlinDetector#hasSerializableAnnotation utility method designed to detect types annotated with `@Serializable` at type or generics level. See gh-35761
This commit is contained in:
@@ -38,6 +38,8 @@ public abstract class KotlinDetector {
|
||||
|
||||
private static final @Nullable Class<? extends Annotation> KOTLIN_JVM_INLINE;
|
||||
|
||||
private static final @Nullable Class<? extends Annotation> KOTLIN_SERIALIZABLE;
|
||||
|
||||
private static final @Nullable Class<?> KOTLIN_COROUTINE_CONTINUATION;
|
||||
|
||||
// For ConstantFieldFeature compliance, otherwise could be deduced from kotlinMetadata
|
||||
@@ -49,6 +51,7 @@ public abstract class KotlinDetector {
|
||||
ClassLoader classLoader = KotlinDetector.class.getClassLoader();
|
||||
Class<?> metadata = null;
|
||||
Class<?> jvmInline = null;
|
||||
Class<?> serializable = null;
|
||||
Class<?> coroutineContinuation = null;
|
||||
try {
|
||||
metadata = ClassUtils.forName("kotlin.Metadata", classLoader);
|
||||
@@ -58,6 +61,12 @@ public abstract class KotlinDetector {
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JVM inline support not available
|
||||
}
|
||||
try {
|
||||
serializable = ClassUtils.forName("kotlinx.serialization.Serializable", classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Kotlin Serialization not available
|
||||
}
|
||||
try {
|
||||
coroutineContinuation = ClassUtils.forName("kotlin.coroutines.Continuation", classLoader);
|
||||
}
|
||||
@@ -72,6 +81,7 @@ public abstract class KotlinDetector {
|
||||
KOTLIN_PRESENT = (KOTLIN_METADATA != null);
|
||||
KOTLIN_REFLECT_PRESENT = ClassUtils.isPresent("kotlin.reflect.full.KClasses", classLoader);
|
||||
KOTLIN_JVM_INLINE = (Class<? extends Annotation>) jvmInline;
|
||||
KOTLIN_SERIALIZABLE = (Class<? extends Annotation>) serializable;
|
||||
KOTLIN_COROUTINE_CONTINUATION = coroutineContinuation;
|
||||
}
|
||||
|
||||
@@ -125,4 +135,26 @@ public abstract class KotlinDetector {
|
||||
return (KOTLIN_JVM_INLINE != null && clazz.getDeclaredAnnotation(KOTLIN_JVM_INLINE) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given {@code ResolvableType} is annotated with {@code @kotlinx.serialization.Serializable}
|
||||
* at type or generics level.
|
||||
* @since 7.0
|
||||
*/
|
||||
public static boolean hasSerializableAnnotation(ResolvableType type) {
|
||||
Class<?> resolvedClass = type.resolve();
|
||||
if (KOTLIN_SERIALIZABLE == null || resolvedClass == null) {
|
||||
return false;
|
||||
}
|
||||
if (resolvedClass.isAnnotationPresent(KOTLIN_SERIALIZABLE)) {
|
||||
return true;
|
||||
}
|
||||
@Nullable Class<?>[] resolvedGenerics = type.resolveGenerics();
|
||||
for (Class<?> resolvedGeneric : resolvedGenerics) {
|
||||
if (resolvedGeneric != null && resolvedGeneric.isAnnotationPresent(KOTLIN_SERIALIZABLE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.core
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
@@ -46,7 +47,26 @@ class KotlinDetectorTests {
|
||||
Assertions.assertThat(KotlinDetector.isInlineClass(KotlinDetectorTests::class.java)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hasSerializableAnnotation() {
|
||||
Assertions.assertThat(KotlinDetector.hasSerializableAnnotation(ResolvableType.forClass(WithoutSerializable::class.java))).isFalse()
|
||||
Assertions.assertThat(KotlinDetector.hasSerializableAnnotation(ResolvableType.forClass(WithSerializable::class.java))).isTrue()
|
||||
|
||||
Assertions.assertThat(KotlinDetector.hasSerializableAnnotation(ResolvableType.forClassWithGenerics(List::class.java, WithoutSerializable::class.java))).isFalse()
|
||||
Assertions.assertThat(KotlinDetector.hasSerializableAnnotation(ResolvableType.forClassWithGenerics(List::class.java, WithSerializable::class.java))).isTrue()
|
||||
|
||||
Assertions.assertThat(KotlinDetector.hasSerializableAnnotation(ResolvableType.forClassWithGenerics(Map::class.java, String::class.java, WithoutSerializable::class.java))).isFalse()
|
||||
Assertions.assertThat(KotlinDetector.hasSerializableAnnotation(ResolvableType.forClassWithGenerics(Map::class.java, String::class.java, WithSerializable::class.java))).isTrue()
|
||||
|
||||
Assertions.assertThat(KotlinDetector.hasSerializableAnnotation(ResolvableType.NONE)).isFalse()
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class ValueClass(val value: String)
|
||||
|
||||
data class WithoutSerializable(val value: String)
|
||||
|
||||
@Serializable
|
||||
data class WithSerializable(val value: String)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user