This is an automated email from the ASF dual-hosted git repository.

crazyhzm pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.3 by this push:
     new 4604b8074a Support for automatic identification of serialization 
classes and generation of native image configuration (#12433)
4604b8074a is described below

commit 4604b8074ab8bc60ce3eac2a54ed0e54457fea58
Author: huazhongming <[email protected]>
AuthorDate: Wed May 31 16:05:54 2023 +0800

    Support for automatic identification of serialization classes and 
generation of native image configuration (#12433)
    
    Signed-off-by: crazyhzm <[email protected]>
---
 ...eferenceAnnotationWithAotBeanPostProcessor.java | 76 +++++++++++-----------
 .../ServiceAnnotationWithAotPostProcessor.java     |  4 +-
 .../dubbo/config/spring6/utils/AotUtils.java       | 41 ++++++++++++
 3 files changed, 83 insertions(+), 38 deletions(-)

diff --git 
a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java
 
b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java
index bcb2917b88..54d660b14c 100644
--- 
a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java
+++ 
b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java
@@ -35,6 +35,7 @@ import 
org.apache.dubbo.config.spring.reference.ReferenceBeanSupport;
 import org.apache.dubbo.config.spring.util.SpringCompatUtils;
 import 
org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedFieldValueResolver;
 import 
org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedMethodArgumentsResolver;
+import org.apache.dubbo.config.spring6.utils.AotUtils;
 import org.apache.dubbo.rpc.service.Destroyable;
 import org.apache.dubbo.rpc.service.EchoService;
 import org.apache.dubbo.rpc.service.GenericService;
@@ -120,7 +121,7 @@ import static org.springframework.util.StringUtils.hasText;
  * @since 2.5.7
  */
 public class ReferenceAnnotationWithAotBeanPostProcessor extends 
AbstractAnnotationBeanPostProcessor
-    implements ApplicationContextAware, BeanRegistrationAotProcessor, 
BeanFactoryPostProcessor {
+        implements ApplicationContextAware, BeanRegistrationAotProcessor, 
BeanFactoryPostProcessor {
 
     /**
      * The bean name of {@link ReferenceAnnotationWithAotBeanPostProcessor}
@@ -135,10 +136,10 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
     private final ErrorTypeAwareLogger logger = 
LoggerFactory.getErrorTypeAwareLogger(getClass());
 
     private final ConcurrentMap<InjectionMetadata.InjectedElement, String> 
injectedFieldReferenceBeanCache =
-        new ConcurrentHashMap<>(CACHE_SIZE);
+            new ConcurrentHashMap<>(CACHE_SIZE);
 
     private final ConcurrentMap<InjectionMetadata.InjectedElement, String> 
injectedMethodReferenceBeanCache =
-        new ConcurrentHashMap<>(CACHE_SIZE);
+            new ConcurrentHashMap<>(CACHE_SIZE);
 
     private ApplicationContext applicationContext;
 
@@ -262,8 +263,8 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
         if (beanClass == null) {
             String beanMethodSignature = 
factoryMethodMetadata.getDeclaringClassName() + "#" + 
factoryMethodMetadata.getMethodName() + "()";
             throw new BeanCreationException("The ReferenceBean is missing 
necessary generic type, which returned by the @Bean method of Java-config 
class. " +
-                "The generic type of the returned ReferenceBean must be 
specified as the referenced interface type, " +
-                "such as ReferenceBean<DemoService>. Please check bean method: 
" + beanMethodSignature);
+                    "The generic type of the returned ReferenceBean must be 
specified as the referenced interface type, " +
+                    "such as ReferenceBean<DemoService>. Please check bean 
method: " + beanMethodSignature);
         }
 
         // get dubbo reference annotation attributes
@@ -295,10 +296,10 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
             if (!StringUtils.isEquals(interfaceName, beanClass.getName()) && 
beanClass != GenericService.class) {
                 String beanMethodSignature = 
factoryMethodMetadata.getDeclaringClassName() + "#" + 
factoryMethodMetadata.getMethodName() + "()";
                 throw new BeanCreationException("The 'interfaceClass' or 
'interfaceName' attribute value of @DubboReference annotation " +
-                    "is inconsistent with the generic type of the 
ReferenceBean returned by the bean method. " +
-                    "The interface class of @DubboReference is: " + 
interfaceName + ", but return ReferenceBean<" + beanClass.getName() + ">. " +
-                    "Please remove the 'interfaceClass' and 'interfaceName' 
attributes from @DubboReference annotation. " +
-                    "Please check bean method: " + beanMethodSignature);
+                        "is inconsistent with the generic type of the 
ReferenceBean returned by the bean method. " +
+                        "The interface class of @DubboReference is: " + 
interfaceName + ", but return ReferenceBean<" + beanClass.getName() + ">. " +
+                        "Please remove the 'interfaceClass' and 
'interfaceName' attributes from @DubboReference annotation. " +
+                        "Please check bean method: " + beanMethodSignature);
             }
 
             Class interfaceClass = beanClass;
@@ -352,7 +353,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
      * @see #postProcessProperties
      */
     public PropertyValues postProcessPropertyValues(
-        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String 
beanName) throws BeansException {
+            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String 
beanName) throws BeansException {
         return postProcessProperties(pvs, bean, beanName);
     }
 
@@ -363,7 +364,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
      */
     @Override
     public PropertyValues postProcessProperties(PropertyValues pvs, Object 
bean, String beanName)
-        throws BeansException {
+            throws BeansException {
         try {
             AnnotatedInjectionMetadata metadata = 
findInjectionMetadata(beanName, bean.getClass(), pvs);
             prepareInjection(metadata);
@@ -372,7 +373,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
             throw ex;
         } catch (Throwable ex) {
             throw new BeanCreationException(beanName, "Injection of @" + 
getAnnotationType().getSimpleName()
-                + " dependencies is failed", ex);
+                    + " dependencies is failed", ex);
         }
         return pvs;
     }
@@ -504,16 +505,16 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
             // bean name from attribute 'id' or java-config bean, cannot be 
renamed
             if (!renameable) {
                 throw new BeanCreationException("Already exists another bean 
definition with the same bean name [" + referenceBeanName + "], " +
-                    "but cannot rename the reference bean name (specify the id 
attribute or java-config bean), " +
-                    "please modify the name of one of the beans: " +
-                    "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + 
checkLocation);
+                        "but cannot rename the reference bean name (specify 
the id attribute or java-config bean), " +
+                        "please modify the name of one of the beans: " +
+                        "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". 
" + checkLocation);
             }
 
             // the prev bean type is different, rename the new reference bean
             int index = 2;
             String newReferenceBeanName = null;
             while (newReferenceBeanName == null || 
beanDefinitionRegistry.containsBeanDefinition(newReferenceBeanName)
-                || beanDefinitionRegistry.isAlias(newReferenceBeanName)) {
+                    || beanDefinitionRegistry.isAlias(newReferenceBeanName)) {
                 newReferenceBeanName = referenceBeanName + "#" + index;
                 index++;
                 // double check found same name and reference key
@@ -524,9 +525,9 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
             newBeanDesc = newReferenceBeanName + "[" + referenceKey + "]";
 
             logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "Already exists 
another bean definition with the same bean name [" + referenceBeanName + "], " +
-                "rename dubbo reference bean to [" + newReferenceBeanName + 
"]. " +
-                "It is recommended to modify the name of one of the beans to 
avoid injection problems. " +
-                "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + 
checkLocation);
+                    "rename dubbo reference bean to [" + newReferenceBeanName 
+ "]. " +
+                    "It is recommended to modify the name of one of the beans 
to avoid injection problems. " +
+                    "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + 
checkLocation);
             referenceBeanName = newReferenceBeanName;
         }
         attributes.put(ReferenceAttributes.ID, referenceBeanName);
@@ -664,19 +665,19 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
         @Override
         public void applyTo(GenerationContext generationContext, 
BeanRegistrationCode beanRegistrationCode) {
             GeneratedClass generatedClass = 
generationContext.getGeneratedClasses()
-                .addForFeatureComponent("DubboReference", this.target, type -> 
{
-                    type.addJavadoc("DubboReference for {@link $T}.", 
this.target);
-                    
type.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
-                });
+                    .addForFeatureComponent("DubboReference", this.target, 
type -> {
+                        type.addJavadoc("DubboReference for {@link $T}.", 
this.target);
+                        
type.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
+                    });
             GeneratedMethod generateMethod = 
generatedClass.getMethods().add("apply", method -> {
                 method.addJavadoc("Apply the dubbo reference.");
                 method.addModifiers(javax.lang.model.element.Modifier.PUBLIC,
-                    javax.lang.model.element.Modifier.STATIC);
+                        javax.lang.model.element.Modifier.STATIC);
                 method.addParameter(RegisteredBean.class, 
REGISTERED_BEAN_PARAMETER);
                 method.addParameter(this.target, INSTANCE_PARAMETER);
                 method.returns(this.target);
                 method.addCode(generateMethodCode(generatedClass.getName(),
-                    generationContext.getRuntimeHints()));
+                        generationContext.getRuntimeHints()));
             });
             
beanRegistrationCode.addInstancePostProcessor(generateMethod.toMethodReference());
 
@@ -690,13 +691,13 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
             if 
(!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getFieldElements())) {
                 for (AnnotatedInjectElement referenceElement : 
this.annotatedInjectionMetadata.getFieldElements()) {
                     code.addStatement(generateMethodStatementForElement(
-                        targetClassName, referenceElement, hints));
+                            targetClassName, referenceElement, hints));
                 }
             }
             if 
(!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getMethodElements())) 
{
                 for (AnnotatedInjectElement referenceElement : 
this.annotatedInjectionMetadata.getMethodElements()) {
                     code.addStatement(generateMethodStatementForElement(
-                        targetClassName, referenceElement, hints));
+                            targetClassName, referenceElement, hints));
                 }
             }
             code.addStatement("return $L", INSTANCE_PARAMETER);
@@ -712,6 +713,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
 
             try {
                 Class<?> c = referenceElement.getInjectedType();
+                AotUtils.registerSerializationHint(c, hints);
                 hints.reflection().registerType(TypeReference.of(c), 
MemberCategory.INVOKE_PUBLIC_METHODS);
                 hints.proxies().registerJdkProxy(c, EchoService.class, 
Destroyable.class);
                 hints.proxies().registerJdkProxy(c, EchoService.class, 
Destroyable.class, SpringProxy.class, Advised.class, DecoratingProxy.class);
@@ -721,14 +723,14 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
 
             if (member instanceof Field) {
                 return generateMethodStatementForField(
-                    targetClassName, (Field) member, attributes, 
injectedObject, hints);
+                        targetClassName, (Field) member, attributes, 
injectedObject, hints);
             }
             if (member instanceof Method) {
                 return generateMethodStatementForMethod(
-                    targetClassName, (Method) member, attributes, 
injectedObject, hints);
+                        targetClassName, (Method) member, attributes, 
injectedObject, hints);
             }
             throw new IllegalStateException(
-                "Unsupported member type " + member.getClass().getName());
+                    "Unsupported member type " + member.getClass().getName());
         }
 
         private CodeBlock generateMethodStatementForField(ClassName 
targetClassName,
@@ -736,17 +738,17 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
 
             hints.reflection().registerField(field);
             CodeBlock resolver = CodeBlock.of("$T.$L($S)",
-                ReferencedFieldValueResolver.class,
-                "forRequiredField", field.getName());
+                    ReferencedFieldValueResolver.class,
+                    "forRequiredField", field.getName());
             CodeBlock shortcutResolver = CodeBlock.of("$L.withShortcut($S)", 
resolver, injectedObject);
             AccessControl accessControl = AccessControl.forMember(field);
 
             if (!accessControl.isAccessibleFrom(targetClassName)) {
                 return CodeBlock.of("$L.resolveAndSet($L, $L)", 
shortcutResolver,
-                    REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER);
+                        REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER);
             }
             return CodeBlock.of("$L.$L = $L.resolve($L)", INSTANCE_PARAMETER,
-                field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER);
+                    field.getName(), shortcutResolver, 
REGISTERED_BEAN_PARAMETER);
         }
 
         private CodeBlock generateMethodStatementForMethod(ClassName 
targetClassName,
@@ -774,9 +776,9 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
             } else {
                 hints.reflection().registerMethod(method, 
ExecutableMode.INTROSPECT);
                 CodeBlock arguments = new 
AutowiredArgumentsCodeGenerator(this.target,
-                    method).generateCode(method.getParameterTypes());
+                        method).generateCode(method.getParameterTypes());
                 CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)",
-                    INSTANCE_PARAMETER, method.getName(), arguments);
+                        INSTANCE_PARAMETER, method.getName(), arguments);
                 code.add(".resolve($L, $L)", REGISTERED_BEAN_PARAMETER, 
injectionCode);
             }
             return code.build();
@@ -830,7 +832,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor 
extends AbstractAnnotat
         private void registerProxyIfNecessary(RuntimeHints runtimeHints, 
DependencyDescriptor dependencyDescriptor) {
             if (this.candidateResolver != null) {
                 Class<?> proxyClass =
-                    
this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null);
+                        
this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null);
                 if (proxyClass != null) {
                     ClassHintUtils.registerProxyIfNecessary(proxyClass, 
runtimeHints);
                 }
diff --git 
a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java
 
b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java
index 384754803a..ee5b17d001 100644
--- 
a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java
+++ 
b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.spring.ServiceBean;
 import 
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor;
 import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser;
+import org.apache.dubbo.config.spring6.utils.AotUtils;
 import org.springframework.aot.generate.GenerationContext;
 import org.springframework.aot.hint.MemberCategory;
 import org.springframework.aot.hint.TypeReference;
@@ -86,7 +87,8 @@ public class ServiceAnnotationWithAotPostProcessor extends 
ServiceAnnotationPost
         @Override
         public void applyTo(GenerationContext generationContext, 
BeanRegistrationCode beanRegistrationCode) {
             
generationContext.getRuntimeHints().reflection().registerType(TypeReference.of(cl),
-                MemberCategory.INVOKE_PUBLIC_METHODS);
+                    MemberCategory.INVOKE_PUBLIC_METHODS);
+            AotUtils.registerSerializationHint(cl, 
generationContext.getRuntimeHints());
 
         }
     }
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
new file mode 100644
index 0000000000..b6b686aee8
--- /dev/null
+++ 
b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/utils/AotUtils.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.TypeReference;
+
+import java.util.Arrays;
+
+
+public class AotUtils {
+
+    private AotUtils(){
+
+    }
+
+    public static void registerSerializationHint(Class<?> injectType, 
RuntimeHints hints) {
+        Arrays.stream(injectType.getMethods()).forEach((method) -> {
+            Arrays.stream(method.getParameterTypes()).forEach((cl) -> {
+                hints.serialization().registerType(TypeReference.of(cl));
+            });
+
+            
hints.serialization().registerType(TypeReference.of(method.getReturnType()));
+        });
+    }
+}

Reply via email to