diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/utils/AotUtils.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/utils/AotUtils.java index d4b056045f..c96d4c33c8 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/utils/AotUtils.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/utils/AotUtils.java @@ -21,6 +21,8 @@ import org.apache.dubbo.common.compiler.support.ClassUtils; import java.io.Serializable; import java.util.Arrays; import java.util.Date; +import java.util.LinkedHashSet; +import java.util.Set; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; @@ -30,25 +32,34 @@ public class AotUtils { private AotUtils() {} public static void registerSerializationForService(Class serviceType, RuntimeHints hints) { + Set> serializationTypeCache = new LinkedHashSet<>(); Arrays.stream(serviceType.getMethods()).forEach((method) -> { Arrays.stream(method.getParameterTypes()) - .forEach((parameterType) -> registerSerializationType(parameterType, hints)); + .forEach( + (parameterType) -> registerSerializationType(parameterType, hints, serializationTypeCache)); - registerSerializationType(method.getReturnType(), hints); + registerSerializationType(method.getReturnType(), hints, serializationTypeCache); }); } - private static void registerSerializationType(Class registerType, RuntimeHints hints) { + private static void registerSerializationType( + Class registerType, RuntimeHints hints, Set> serializationTypeCache) { if (isPrimitive(registerType)) { hints.serialization().registerType(TypeReference.of(ClassUtils.getBoxedClass(registerType))); + serializationTypeCache.add(registerType); } else { if (Serializable.class.isAssignableFrom(registerType)) { hints.serialization().registerType(TypeReference.of(registerType)); + serializationTypeCache.add(registerType); - Arrays.stream(registerType.getDeclaredFields()) - .forEach((field -> registerSerializationType(field.getType(), hints))); + Arrays.stream(registerType.getDeclaredFields()).forEach((field -> { + if (!serializationTypeCache.contains(field.getType())) { + registerSerializationType(field.getType(), hints, serializationTypeCache); + serializationTypeCache.add(field.getType()); + } + })); - registerSerializationType(registerType.getSuperclass(), hints); + registerSerializationType(registerType.getSuperclass(), hints, serializationTypeCache); } } } diff --git a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/AotUtilsTest.java b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/AotUtilsTest.java index 392518ba7b..32a9499e73 100644 --- a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/AotUtilsTest.java +++ b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/AotUtilsTest.java @@ -71,4 +71,34 @@ public class AotUtilsTest { Assertions.assertTrue(containHelloRequestSuper.get()); Assertions.assertTrue(containHelloResponse.get()); } + + @Test + void registerSerializationForCircularDependencyFieldTest() { + RuntimeHints runtimeHints = new RuntimeHints(); + AotUtils.registerSerializationForService(CircularDependencyDemoService.class, runtimeHints); + AtomicBoolean containDemoA = new AtomicBoolean(false); + runtimeHints.serialization().javaSerializationHints().forEach(s -> { + if (s.getType().getName().equals(DemoA.class.getName())) { + containDemoA.set(true); + } + }); + AtomicBoolean containDemoB = new AtomicBoolean(false); + runtimeHints.serialization().javaSerializationHints().forEach(s -> { + if (s.getType().getName().equals(DemoB.class.getName())) { + containDemoB.set(true); + } + }); + + Assertions.assertTrue(containDemoA.get()); + Assertions.assertTrue(containDemoB.get()); + + AotUtils.registerSerializationForService(DemoService.class, runtimeHints); + AtomicBoolean containSexEnum = new AtomicBoolean(false); + runtimeHints.serialization().javaSerializationHints().forEach(s -> { + if (s.getType().getName().equals(SexEnum.class.getName())) { + containSexEnum.set(true); + } + }); + Assertions.assertTrue(containSexEnum.get()); + } } diff --git a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/CircularDependencyDemoService.java b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/CircularDependencyDemoService.java new file mode 100644 index 0000000000..ecc9c6c086 --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/CircularDependencyDemoService.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.config.spring6.utils; + +public interface CircularDependencyDemoService { + String sayHello(DemoA a); +} diff --git a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/DemoA.java b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/DemoA.java new file mode 100644 index 0000000000..e6aefe50b0 --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/DemoA.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.config.spring6.utils; + +import java.io.Serializable; + +public class DemoA implements Serializable { + private DemoB b; +} diff --git a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/DemoB.java b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/DemoB.java new file mode 100644 index 0000000000..91c01c7987 --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/DemoB.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.config.spring6.utils; + +import java.io.Serializable; + +public class DemoB implements Serializable { + private DemoA a; +} diff --git a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/Person.java b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/Person.java index de83f4b8d0..ba49fbf37e 100644 --- a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/Person.java +++ b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/Person.java @@ -22,8 +22,11 @@ public class Person implements Serializable { private String name; - public Person(String name) { + private SexEnum sex; + + public Person(String name, SexEnum sex) { this.name = name; + this.sex = sex; } public String getName() { @@ -33,4 +36,12 @@ public class Person implements Serializable { public void setName(String name) { this.name = name; } + + public SexEnum getSex() { + return sex; + } + + public void setSex(SexEnum sex) { + this.sex = sex; + } } diff --git a/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/SexEnum.java b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/SexEnum.java new file mode 100644 index 0000000000..5a5bee5564 --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/test/java/org/apache/dubbo/config/spring6/utils/SexEnum.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.config.spring6.utils; + +public enum SexEnum { + BOY("boy"), + GIRL("girl"); + + private final String desc; + + SexEnum(String desc) { + this.desc = desc; + } + + public String getDesc() { + return desc; + } +}