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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new 05dbea9  Support export generic service with @DubboService annotation, 
without service interface locally (#8174)
05dbea9 is described below

commit 05dbea9329d1fdca61dc557b87de9c8d352b8c9b
Author: Gong Dewei <[email protected]>
AuthorDate: Wed Jun 30 11:19:11 2021 +0800

    Support export generic service with @DubboService annotation, without 
service interface locally (#8174)
---
 .../annotation/ServiceAnnotationPostProcessor.java | 34 +++++------
 .../factory/annotation/ServiceBeanNameBuilder.java |  4 ++
 .../config/spring/util/DubboAnnotationUtils.java   | 67 +++++++-------------
 .../javaconfig/JavaConfigReferenceBeanTest.java    | 71 ++++++++++++++++++----
 .../reference/javaconfig/consumer.properties       |  6 +-
 .../config/spring/schema/GenericServiceTest.java   |  1 +
 .../META-INF/spring/dubbo-generic-consumer.xml     |  4 +-
 7 files changed, 107 insertions(+), 80 deletions(-)

diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java
index 4dffaf4..ec5229c 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java
@@ -80,7 +80,7 @@ import static com.alibaba.spring.util.ObjectUtils.of;
 import static java.util.Arrays.asList;
 import static 
org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues;
 import static 
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create;
-import static 
org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveServiceInterfaceClass;
+import static 
org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveInterfaceName;
 import static 
org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
 import static 
org.springframework.context.annotation.AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR;
 import static 
org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
@@ -303,17 +303,17 @@ public class ServiceAnnotationPostProcessor implements 
BeanDefinitionRegistryPos
         // The attributes of @Service annotation
         Map<String, Object> serviceAnnotationAttributes = 
AnnotationUtils.getAttributes(service, true);
 
-        Class<?> interfaceClass = 
resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
+        String serviceInterface = 
resolveInterfaceName(serviceAnnotationAttributes, beanClass);
 
         String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
 
         // ServiceBean Bean name
-        String beanName = generateServiceBeanName(serviceAnnotationAttributes, 
interfaceClass);
+        String beanName = generateServiceBeanName(serviceAnnotationAttributes, 
serviceInterface);
 
         AbstractBeanDefinition serviceBeanDefinition =
-                buildServiceBeanDefinition(serviceAnnotationAttributes, 
interfaceClass, annotatedServiceBeanName);
+                buildServiceBeanDefinition(serviceAnnotationAttributes, 
serviceInterface, annotatedServiceBeanName);
 
-        registerServiceBeanDefinition(beanName, serviceBeanDefinition, 
interfaceClass);
+        registerServiceBeanDefinition(beanName, serviceBeanDefinition, 
serviceInterface);
 
     }
 
@@ -337,12 +337,12 @@ public class ServiceAnnotationPostProcessor implements 
BeanDefinitionRegistryPos
      * Generates the bean name of {@link ServiceBean}
      *
      * @param serviceAnnotationAttributes
-     * @param interfaceClass              the class of interface annotated 
{@link Service}
+     * @param serviceInterface              the class of interface annotated 
{@link Service}
      * @return ServiceBean@interfaceClassName#annotatedServiceBeanName
      * @since 2.7.3
      */
-    private String generateServiceBeanName(Map<String, Object> 
serviceAnnotationAttributes, Class<?> interfaceClass) {
-        ServiceBeanNameBuilder builder = create(interfaceClass, environment)
+    private String generateServiceBeanName(Map<String, Object> 
serviceAnnotationAttributes, String serviceInterface) {
+        ServiceBeanNameBuilder builder = create(serviceInterface, environment)
                 .group((String) serviceAnnotationAttributes.get("group"))
                 .version((String) serviceAnnotationAttributes.get("version"));
         return builder.build();
@@ -380,13 +380,13 @@ public class ServiceAnnotationPostProcessor implements 
BeanDefinitionRegistryPos
      *
      *
      * @param serviceAnnotationAttributes
-     * @param interfaceClass
+     * @param serviceInterface
      * @param refServiceBeanName
      * @return
      * @since 2.7.3
      */
     private AbstractBeanDefinition buildServiceBeanDefinition(Map<String, 
Object> serviceAnnotationAttributes,
-                                                              Class<?> 
interfaceClass,
+                                                              String 
serviceInterface,
                                                               String 
refServiceBeanName) {
 
         BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
@@ -405,7 +405,7 @@ public class ServiceAnnotationPostProcessor implements 
BeanDefinitionRegistryPos
         // References "ref" property to annotated-@Service Bean
         addPropertyReference(builder, "ref", refServiceBeanName);
         // Set interface
-        builder.addPropertyValue("interface", interfaceClass.getName());
+        builder.addPropertyValue("interface", serviceInterface);
         // Convert parameters into map
         builder.addPropertyValue("parameters", convertParameters((String[]) 
serviceAnnotationAttributes.get("parameters")));
         // Add methods parameters
@@ -563,20 +563,20 @@ public class ServiceAnnotationPostProcessor implements 
BeanDefinitionRegistryPos
         String returnTypeName = 
refServiceBeanDefinition.getFactoryMethodMetadata().getReturnTypeName();
         Class<?> beanClass = resolveClassName(returnTypeName, classLoader);
 
-        Class<?> interfaceClass = 
resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
+        String serviceInterface = 
resolveInterfaceName(serviceAnnotationAttributes, beanClass);
 
         // ServiceBean Bean name
-        String serviceBeanName = 
generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);
+        String serviceBeanName = 
generateServiceBeanName(serviceAnnotationAttributes, serviceInterface);
 
-        AbstractBeanDefinition serviceBeanDefinition = 
buildServiceBeanDefinition(serviceAnnotationAttributes, interfaceClass, 
refServiceBeanName);
+        AbstractBeanDefinition serviceBeanDefinition = 
buildServiceBeanDefinition(serviceAnnotationAttributes, serviceInterface, 
refServiceBeanName);
 
         // set id
         serviceBeanDefinition.getPropertyValues().add(Constants.ID, 
serviceBeanName);
 
-        registerServiceBeanDefinition(serviceBeanName, serviceBeanDefinition, 
interfaceClass);
+        registerServiceBeanDefinition(serviceBeanName, serviceBeanDefinition, 
serviceInterface);
     }
 
-    private void registerServiceBeanDefinition(String serviceBeanName, 
AbstractBeanDefinition serviceBeanDefinition, Class<?> interfaceClass) {
+    private void registerServiceBeanDefinition(String serviceBeanName, 
AbstractBeanDefinition serviceBeanDefinition, String serviceInterface) {
         // check service bean
         if (registry.containsBeanDefinition(serviceBeanName)) {
             BeanDefinition existingDefinition = 
registry.getBeanDefinition(serviceBeanName);
@@ -585,7 +585,7 @@ public class ServiceAnnotationPostProcessor implements 
BeanDefinitionRegistryPos
                 return;
             }
 
-            String msg = "Found duplicated BeanDefinition of service interface 
[" + interfaceClass.getName() + "] with bean name [" + serviceBeanName +
+            String msg = "Found duplicated BeanDefinition of service interface 
[" + serviceInterface + "] with bean name [" + serviceBeanName +
                     "], existing definition [ " + existingDefinition + "], new 
definition [" + serviceBeanDefinition + "]";
             logger.error(msg);
             throw new 
BeanDefinitionStoreException(serviceBeanDefinition.getResourceDescription(), 
serviceBeanName, msg);
diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
index 7cd04ec..d80bc97 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
@@ -82,6 +82,10 @@ public class ServiceBeanNameBuilder {
         return new ServiceBeanNameBuilder(interfaceClass, environment);
     }
 
+    public static ServiceBeanNameBuilder create(String interfaceClass, 
Environment environment) {
+        return new ServiceBeanNameBuilder(interfaceClass, environment);
+    }
+
     public static ServiceBeanNameBuilder create(Service service, Class<?> 
interfaceClass, Environment environment) {
         return create(getAnnotationAttributes(service, false, false), 
interfaceClass, environment);
     }
diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
index 7fe662f..e9aaa8a 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
@@ -16,17 +16,17 @@
  */
 package org.apache.dubbo.config.spring.util;
 
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.annotation.Service;
 
+import org.apache.dubbo.rpc.service.GenericService;
 import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
 
 import java.util.Map;
 
 import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
 import static org.springframework.util.ClassUtils.getAllInterfacesForClass;
-import static org.springframework.util.ClassUtils.resolveClassName;
 import static org.springframework.util.StringUtils.hasText;
 
 /**
@@ -60,73 +60,48 @@ public class DubboAnnotationUtils {
     }
 
     /**
-     * Resolve the interface name from annotation attributes
+     * Resolve the service interface name from @Service annotation attributes.
+     * <p/>
+     * Note: the service interface class maybe not found locally if is a 
generic service.
      *
-     * @param attributes             annotation attributes instance, may be 
{@link Service @Service} or {@link Reference @Reference}
+     * @param attributes             annotation attributes of {@link Service 
@Service}
      * @param defaultInterfaceClass the default class of interface
      * @return the interface name if found
      * @throws IllegalStateException if interface name was not found
      */
     public static String resolveInterfaceName(Map<String, Object> attributes, 
Class<?> defaultInterfaceClass) {
         Boolean generic = getAttribute(attributes, "generic");
-        if (generic != null && generic) {
-            // it's a generic reference
-            String interfaceClassName = getAttribute(attributes, 
"interfaceName");
-            Assert.hasText(interfaceClassName,
-                    "@Reference interfaceName() must be present when reference 
a generic service!");
+        // 1. get from DubboService.interfaceName()
+        String interfaceClassName = getAttribute(attributes, "interfaceName");
+        if (StringUtils.hasText(interfaceClassName)) {
+            if (GenericService.class.getName().equals(interfaceClassName) ||
+                
com.alibaba.dubbo.rpc.service.GenericService.class.getName().equals(interfaceClassName))
 {
+                throw new IllegalStateException("@Service interfaceName() 
cannot be GenericService: " + interfaceClassName);
+            }
             return interfaceClassName;
         }
-        return resolveServiceInterfaceClass(attributes, 
defaultInterfaceClass).getName();
-    }
-
-    /**
-     * Resolve the interface class of Dubbo Service annotation from the 
specified
-     * annotation attributes and annotated class.
-     *
-     * @param attributes            annotation attributes
-     * @param defaultInterfaceClass the annotated class.
-     * @return the class of Dubbo Service interface
-     * @throws IllegalArgumentException if can't resolved
-     */
-    public static Class<?> resolveServiceInterfaceClass(Map<String, Object> 
attributes, Class<?> defaultInterfaceClass)
-            throws IllegalArgumentException {
-
-        ClassLoader classLoader = defaultInterfaceClass != null ? 
defaultInterfaceClass.getClassLoader() : 
Thread.currentThread().getContextClassLoader();
 
+        // 2. get from DubboService.interfaceClass()
         Class<?> interfaceClass = getAttribute(attributes, "interfaceClass");
-
         if (interfaceClass == null || void.class.equals(interfaceClass)) { // 
default or set void.class for purpose.
-
             interfaceClass = null;
-
-            String interfaceClassName = getAttribute(attributes, 
"interfaceName");
-
-            if (hasText(interfaceClassName)) {
-                if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
-                    interfaceClass = resolveClassName(interfaceClassName, 
classLoader);
-                }
-            }
-
+        } else  if (GenericService.class.isAssignableFrom(interfaceClass)) {
+            throw new IllegalStateException("@Service interfaceClass() cannot 
be GenericService :" + interfaceClass.getName());
         }
 
-        if (interfaceClass == null && defaultInterfaceClass != null) {
+        // 3. get from annotation element type, ignore GenericService
+        if (interfaceClass == null && defaultInterfaceClass != null  && 
!GenericService.class.isAssignableFrom(defaultInterfaceClass)) {
             // Find all interfaces from the annotated class
             // To resolve an issue : 
https://github.com/apache/dubbo/issues/3251
             Class<?>[] allInterfaces = 
getAllInterfacesForClass(defaultInterfaceClass);
-
             if (allInterfaces.length > 0) {
                 interfaceClass = allInterfaces[0];
             }
-
         }
 
-        Assert.notNull(interfaceClass,
-                "@Service interfaceClass() or interfaceName() or interface 
class must be present!");
-
-        Assert.isTrue(interfaceClass.isInterface(),
-                "The annotated type must be an interface!");
-
-        return interfaceClass;
+        Assert.notNull(interfaceClass, "@Service interfaceClass() or 
interfaceName() or interface class must be present!");
+        Assert.isTrue(interfaceClass.isInterface(), "The annotated type must 
be an interface!");
+        return interfaceClass.getName();
     }
 
     @Deprecated
diff --git 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java
 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java
index e0b2428..d90d054 100644
--- 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java
+++ 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java
@@ -17,17 +17,22 @@
 package org.apache.dubbo.config.spring.reference.javaconfig;
 
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.annotation.DubboService;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.ReferenceBean;
+import org.apache.dubbo.config.spring.ZooKeeperServer;
 import org.apache.dubbo.config.spring.api.DemoService;
 import org.apache.dubbo.config.spring.api.HelloService;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.impl.HelloServiceImpl;
 import org.apache.dubbo.config.spring.reference.ReferenceBeanBuilder;
+import org.apache.dubbo.rpc.service.GenericException;
 import org.apache.dubbo.rpc.service.GenericService;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import 
org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -41,6 +46,11 @@ import java.util.Map;
 
 public class JavaConfigReferenceBeanTest {
 
+    @BeforeAll
+    public static void beforeAll() {
+        ZooKeeperServer.start();
+    }
+
     @BeforeEach
     public void setUp() {
         DubboBootstrap.reset();
@@ -55,19 +65,19 @@ public class JavaConfigReferenceBeanTest {
     @Test
     public void testAnnotationBean() {
         Assertions.assertEquals(0, 
SpringExtensionFactory.getContexts().size());
-        AnnotationConfigApplicationContext context = new 
AnnotationConfigApplicationContext(ConsumerConfig.class,
+        AnnotationConfigApplicationContext context = new 
AnnotationConfigApplicationContext(CommonConfig.class,
                 AnnotationBeanConfiguration.class);
 
         Map<String, HelloService> helloServiceMap = 
context.getBeansOfType(HelloService.class);
-        Assertions.assertEquals(1, helloServiceMap.size());
+        Assertions.assertEquals(2, helloServiceMap.size());
         Assertions.assertNotNull(helloServiceMap.get("helloService"));
 
         Map<String, GenericService> genericServiceMap = 
context.getBeansOfType(GenericService.class);
-        Assertions.assertEquals(1, genericServiceMap.size());
+        Assertions.assertEquals(3, genericServiceMap.size());
         Assertions.assertNotNull(genericServiceMap.get("genericHelloService"));
 
         Map<String, ReferenceBean> referenceBeanMap = 
context.getBeansOfType(ReferenceBean.class);
-        Assertions.assertEquals(2, referenceBeanMap.size());
+        Assertions.assertEquals(3, referenceBeanMap.size());
         ReferenceBean referenceBean = referenceBeanMap.get("&helloService");
         Assertions.assertEquals("demo", referenceBean.getGroup());
         Assertions.assertEquals(HelloService.class, 
referenceBean.getInterfaceClass());
@@ -78,6 +88,16 @@ public class JavaConfigReferenceBeanTest {
         Assertions.assertEquals(GenericService.class, 
genericHelloServiceReferenceBean.getInterfaceClass());
         Assertions.assertEquals(HelloService.class.getName(), 
genericHelloServiceReferenceBean.getServiceInterface());
 
+        ReferenceBean genericServiceWithoutInterfaceBean = 
referenceBeanMap.get("&genericServiceWithoutInterface");
+        Assertions.assertEquals("demo", 
genericServiceWithoutInterfaceBean.getGroup());
+        Assertions.assertEquals(GenericService.class, 
genericServiceWithoutInterfaceBean.getInterfaceClass());
+        
Assertions.assertEquals("org.apache.dubbo.config.spring.api.LocalMissClass", 
genericServiceWithoutInterfaceBean.getServiceInterface());
+
+        GenericService genericServiceWithoutInterface = 
context.getBean("genericServiceWithoutInterface", GenericService.class);
+        Assertions.assertNotNull(genericServiceWithoutInterface);
+        Object sayHelloResult = 
genericServiceWithoutInterface.$invoke("sayHello", new 
String[]{"java.lang.String"}, new Object[]{"Dubbo"});
+        Assertions.assertEquals("Hello Dubbo", sayHelloResult);
+
         context.close();
         Assertions.assertEquals(1, 
SpringExtensionFactory.getContexts().size());
     }
@@ -85,16 +105,15 @@ public class JavaConfigReferenceBeanTest {
     @Test
     public void testGenericReferenceBean() {
         Assertions.assertEquals(0, 
SpringExtensionFactory.getContexts().size());
-        AnnotationConfigApplicationContext context = new 
AnnotationConfigApplicationContext(ConsumerConfig.class,
+        AnnotationConfigApplicationContext context = new 
AnnotationConfigApplicationContext(CommonConfig.class,
                 ReferenceBeanConfiguration.class);
 
         Map<String, HelloService> helloServiceMap = 
context.getBeansOfType(HelloService.class);
         Assertions.assertEquals(2, helloServiceMap.size());
         Assertions.assertNotNull(helloServiceMap.get("helloService"));
-        Assertions.assertNotNull(helloServiceMap.get("helloService2"));
 
         Map<String, GenericService> genericServiceMap = 
context.getBeansOfType(GenericService.class);
-        Assertions.assertEquals(1, genericServiceMap.size());
+        Assertions.assertEquals(2, genericServiceMap.size());
         Assertions.assertNotNull(genericServiceMap.get("genericHelloService"));
 
         Map<String, ReferenceBean> referenceBeanMap = 
context.getBeansOfType(ReferenceBean.class);
@@ -117,7 +136,7 @@ public class JavaConfigReferenceBeanTest {
         AnnotationConfigApplicationContext context = null;
         try {
             Assertions.assertEquals(0, 
SpringExtensionFactory.getContexts().size());
-            context = new 
AnnotationConfigApplicationContext(ConsumerConfig.class, 
ReferenceBeanWithoutGenericTypeConfiguration.class);
+            context = new 
AnnotationConfigApplicationContext(CommonConfig.class, 
ReferenceBeanWithoutGenericTypeConfiguration.class);
             Assertions.fail("Should not load application");
 
         } catch (Exception e) {
@@ -138,7 +157,7 @@ public class JavaConfigReferenceBeanTest {
         AnnotationConfigApplicationContext context = null;
         try {
             Assertions.assertEquals(0, 
SpringExtensionFactory.getContexts().size());
-            context = new 
AnnotationConfigApplicationContext(ConsumerConfig.class, 
InconsistentBeanConfiguration.class);
+            context = new 
AnnotationConfigApplicationContext(CommonConfig.class, 
InconsistentBeanConfiguration.class);
             Assertions.fail("Should not load application");
         } catch (Exception e) {
             String s = e.toString();
@@ -158,7 +177,7 @@ public class JavaConfigReferenceBeanTest {
         AnnotationConfigApplicationContext context = null;
         try {
             Assertions.assertEquals(0, 
SpringExtensionFactory.getContexts().size());
-            context = new 
AnnotationConfigApplicationContext(ConsumerConfig.class, 
MissingGenericTypeAnnotationBeanConfiguration.class);
+            context = new 
AnnotationConfigApplicationContext(CommonConfig.class, 
MissingGenericTypeAnnotationBeanConfiguration.class);
             Assertions.fail("Should not load application");
         } catch (Exception e) {
             String s = e.toString();
@@ -177,7 +196,7 @@ public class JavaConfigReferenceBeanTest {
         AnnotationConfigApplicationContext context = null;
         try {
             Assertions.assertEquals(0, 
SpringExtensionFactory.getContexts().size());
-            context = new 
AnnotationConfigApplicationContext(ConsumerConfig.class, 
MissingInterfaceTypeAnnotationBeanConfiguration.class);
+            context = new 
AnnotationConfigApplicationContext(CommonConfig.class, 
MissingInterfaceTypeAnnotationBeanConfiguration.class);
             Assertions.fail("Should not load application");
         } catch (Exception e) {
             String s = e.toString();
@@ -193,12 +212,32 @@ public class JavaConfigReferenceBeanTest {
     @Configuration
     @EnableDubbo
     
@PropertySource("classpath:/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties")
-    public static class ConsumerConfig {
+    public static class CommonConfig {
 
         @Bean
         public List<String> testBean(HelloService helloService) {
             return Arrays.asList(helloService.getClass().getName());
         }
+
+        @Bean
+        @DubboService(group = "${myapp.group}")
+        public HelloService helloServiceImpl() {
+            return new HelloServiceImpl();
+        }
+
+        @Bean
+        @DubboService(group = "${myapp.group}", interfaceName = 
"org.apache.dubbo.config.spring.api.LocalMissClass")
+        public GenericService localMissClassGenericServiceImpl() {
+            return new GenericService() {
+                @Override
+                public Object $invoke(String method, String[] parameterTypes, 
Object[] args) throws GenericException {
+                    if ("sayHello".equals(method)) {
+                        return "Hello " + args[0];
+                    }
+                    return null;
+                }
+            };
+        }
     }
 
     @Configuration
@@ -216,6 +255,12 @@ public class JavaConfigReferenceBeanTest {
             return new ReferenceBean();
         }
 
+        @Bean
+        @Reference(group = "${myapp.group}", interfaceName = 
"org.apache.dubbo.config.spring.api.LocalMissClass")
+        public ReferenceBean<GenericService> genericServiceWithoutInterface() {
+            return new ReferenceBean();
+        }
+
     }
 
     @Configuration
@@ -229,7 +274,7 @@ public class JavaConfigReferenceBeanTest {
         }
 
         @Bean
-        public ReferenceBean<HelloService> helloService2() {
+        public ReferenceBean<DemoService> demoService() {
             return new ReferenceBean();
         }
 
diff --git 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties
 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties
index 0eaff32..f2f6ea5 100644
--- 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties
+++ 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties
@@ -1,6 +1,8 @@
 dubbo.application.name=consumer-app
 dubbo.protocol.name=dubbo
 dubbo.protocol.port=-1
-dubbo.registry.address=N/A
-dubbo.reference.org.apache.dubbo.config.spring.api.HelloService.init=false
+dubbo.registry.address=zookeeper://127.0.0.1:2181
+dubbo.reference.org.apache.dubbo.config.spring.api.DemoService.init=false
+#dubbo.reference.org.apache.dubbo.config.spring.api.HelloService.init=false
+#dubbo.consumer.init=false
 myapp.group=demo
diff --git 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
index 105bbdf..2c2b42c 100644
--- 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
+++ 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
@@ -89,6 +89,7 @@ public class GenericServiceTest {
 
         ReferenceConfigBase<Object> reference = 
configManager.getReference("genericServiceWithoutInterfaceRef");
         Assertions.assertNull(reference.getServiceInterfaceClass());
+        
Assertions.assertEquals("org.apache.dubbo.config.spring.api.LocalMissClass", 
reference.getInterface());
         Assertions.assertThrows(ClassNotFoundException.class, () -> 
ClassUtils.forName(reference.getInterface()));
 
     }
diff --git 
a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml
 
b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml
index a103e4f..fd5dde5 100644
--- 
a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml
+++ 
b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml
@@ -35,7 +35,7 @@
                    ref="genericService"/>
 
     <!-- generic service without interface class -->
-    <dubbo:reference id="genericServiceWithoutInterfaceRef" 
interface="org.apache.dubbo.config.spring.api.LocalMissService" generic="true" 
init="false"/>
-    <dubbo:service id="genericServiceWithoutInterface" 
interface="org.apache.dubbo.config.spring.api.LocalMissService" generic="true"
+    <dubbo:reference id="genericServiceWithoutInterfaceRef" 
interface="org.apache.dubbo.config.spring.api.LocalMissClass" generic="true" 
init="false"/>
+    <dubbo:service id="genericServiceWithoutInterface" 
interface="org.apache.dubbo.config.spring.api.LocalMissClass" generic="true"
                    ref="genericService"/>
 </beans>

Reply via email to