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

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


The following commit(s) were added to refs/heads/master by this push:
     new 62a32aa  Polish #4674 & #4470 (#5033)
62a32aa is described below

commit 62a32aa1e073e46bc43711f8fde486e027108742
Author: Mercy Ma <[email protected]>
AuthorDate: Mon Sep 9 10:50:18 2019 +0800

    Polish #4674 & #4470 (#5033)
    
    * Polish /apache/dubbo#4687 : Remove the duplicated test code in 
dubbo-config-spring
    
    * Polish /apache/dubbo#4674 & /apache/dubbo#4470
---
 .../ReferenceAnnotationBeanPostProcessor.java      | 90 ++++++++++++++--------
 .../ReferenceAnnotationBeanPostProcessorTest.java  | 44 ++++++-----
 2 files changed, 83 insertions(+), 51 deletions(-)

diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
index 7feea26..c9c0736 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.config.spring.beans.factory.annotation;
 
 import org.apache.dubbo.config.annotation.Reference;
+import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.ServiceBean;
 import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
@@ -38,13 +39,13 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import static java.lang.reflect.Proxy.newProxyInstance;
 import static 
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create;
 import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttribute;
 import static org.springframework.util.StringUtils.hasText;
@@ -123,22 +124,30 @@ public class ReferenceAnnotationBeanPostProcessor extends 
AnnotationInjectedBean
     protected Object doGetInjectedBean(AnnotationAttributes attributes, Object 
bean, String beanName, Class<?> injectedType,
                                        InjectionMetadata.InjectedElement 
injectedElement) throws Exception {
 
+        /**
+         * The name of bean that annotated Dubbo's {@link Service @Service} in 
local Spring {@link ApplicationContext}
+         */
         String referencedBeanName = buildReferencedBeanName(attributes, 
injectedType);
 
-        ReferenceBean referenceBean = 
buildReferenceBeanIfAbsent(referencedBeanName, attributes, injectedType);
+        /**
+         * The name of bean that is declared by {@link Reference @Reference} 
annotation injection
+         */
+        String referenceBeanName = getReferenceBeanName(attributes, 
injectedType);
+
+        ReferenceBean referenceBean = 
buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);
 
         registerReferenceBean(referencedBeanName, referenceBean, attributes, 
injectedType);
 
         cacheInjectedReferenceBean(referenceBean, injectedElement);
 
-        return buildProxy(referencedBeanName, referenceBean, injectedType);
+        return getOrCreateProxy(referencedBeanName, referenceBeanName, 
referenceBean, injectedType);
     }
 
     /**
      * Register an instance of {@link ReferenceBean} as a Spring Bean
      *
-     * @param referencedBeanName the referenced bean name
-     * @param referenceBean      the instance of {@link ReferenceBean}
+     * @param referencedBeanName The name of bean that annotated Dubbo's 
{@link Service @Service} in the Spring {@link ApplicationContext}
+     * @param referenceBean      the instance of {@link ReferenceBean} is 
about to register into the Spring {@link ApplicationContext}
      * @param attributes         the {@link AnnotationAttributes attributes} 
of {@link Reference @Reference}
      * @param interfaceClass     the {@link Class class} of Service interface
      * @since 2.7.3
@@ -151,7 +160,7 @@ public class ReferenceAnnotationBeanPostProcessor extends 
AnnotationInjectedBean
 
         String beanName = getReferenceBeanName(attributes, interfaceClass);
 
-        if (beanFactory.containsBean(referencedBeanName)) { // If @Service 
bean is local one
+        if (existsServiceBean(referencedBeanName)) { // If @Service bean is 
local one
             /**
              * Get  the @Service's BeanDefinition from {@link BeanFactory}
              * Refer to {@link 
ServiceAnnotationBeanPostProcessor#buildServiceBeanDefinition}
@@ -215,28 +224,41 @@ public class ReferenceAnnotationBeanPostProcessor extends 
AnnotationInjectedBean
         return beanNameBuilder.toString();
     }
 
-    private Object buildProxy(String referencedBeanName, ReferenceBean 
referenceBean, Class<?> injectedType) {
-        InvocationHandler handler = buildInvocationHandler(referencedBeanName, 
referenceBean);
-        return Proxy.newProxyInstance(getClassLoader(), new 
Class[]{injectedType}, handler);
+    private boolean existsServiceBean(String referencedBeanName) {
+        return applicationContext.containsBean(referencedBeanName);
     }
 
-    private InvocationHandler buildInvocationHandler(String 
referencedBeanName, ReferenceBean referenceBean) {
-
-        ReferenceBeanInvocationHandler handler = 
localReferenceBeanInvocationHandlerCache.get(referencedBeanName);
-
-        if (handler == null) {
-            handler = new ReferenceBeanInvocationHandler(referenceBean);
-        }
-
-        if (applicationContext.containsBean(referencedBeanName)) { // Is local 
@Service Bean or not ?
-            // ReferenceBeanInvocationHandler's initialization has to wait for 
current local @Service Bean has been exported.
-            localReferenceBeanInvocationHandlerCache.put(referencedBeanName, 
handler);
-        } else {
-            // Remote Reference Bean should initialize immediately
-            handler.init();
+    /**
+     * Get or Create a proxy of {@link ReferenceBean} for the specified the 
type of Dubbo service interface
+     *
+     * @param referencedBeanName   The name of bean that annotated Dubbo's 
{@link Service @Service} in the Spring {@link ApplicationContext}
+     * @param referenceBeanName    the bean name of {@link ReferenceBean}
+     * @param referenceBean        the instance of {@link ReferenceBean}
+     * @param serviceInterfaceType the type of Dubbo service interface
+     * @return non-null
+     * @since 2.7.4
+     */
+    private Object getOrCreateProxy(String referencedBeanName, String 
referenceBeanName, ReferenceBean referenceBean, Class<?> serviceInterfaceType) {
+        if (existsServiceBean(referencedBeanName)) { // If the local @Service 
Bean exists, build a proxy of ReferenceBean
+            return newProxyInstance(getClassLoader(), new 
Class[]{serviceInterfaceType},
+                    wrapInvocationHandler(referenceBeanName, referenceBean));
+        } else {                                    // ReferenceBean should be 
initialized and get immediately
+            return referenceBean.get();
         }
+    }
 
-        return handler;
+    /**
+     * Wrap an instance of {@link InvocationHandler} that is used to get the 
proxy of {@link ReferenceBean} after
+     * the specified local referenced bean that annotated {@link @Service} 
exported.
+     *
+     * @param referenceBeanName the bean name of {@link ReferenceBean}
+     * @param referenceBean     the instance of {@link ReferenceBean}
+     * @return non-null
+     * @since 2.7.4
+     */
+    private InvocationHandler wrapInvocationHandler(String referenceBeanName, 
ReferenceBean referenceBean) {
+        return 
localReferenceBeanInvocationHandlerCache.computeIfAbsent(referenceBeanName, 
name ->
+                new ReferenceBeanInvocationHandler(referenceBean));
     }
 
     private static class ReferenceBeanInvocationHandler implements 
InvocationHandler {
@@ -273,33 +295,35 @@ public class ReferenceAnnotationBeanPostProcessor extends 
AnnotationInjectedBean
     @Override
     protected String buildInjectedObjectCacheKey(AnnotationAttributes 
attributes, Object bean, String beanName,
                                                  Class<?> injectedType, 
InjectionMetadata.InjectedElement injectedElement) {
-
         return buildReferencedBeanName(attributes, injectedType) +
                 "#source=" + (injectedElement.getMember()) +
                 "#attributes=" + 
AnnotationUtils.resolvePlaceholders(attributes, getEnvironment());
     }
 
-    private String buildReferencedBeanName(AnnotationAttributes attributes, 
Class<?> injectedType) {
-
-        ServiceBeanNameBuilder serviceBeanNameBuilder = create(attributes, 
injectedType, getEnvironment());
-
+    /**
+     * @param attributes           the attributes of {@link Reference 
@Reference}
+     * @param serviceInterfaceType the type of Dubbo's service interface
+     * @return The name of bean that annotated Dubbo's {@link Service 
@Service} in local Spring {@link ApplicationContext}
+     */
+    private String buildReferencedBeanName(AnnotationAttributes attributes, 
Class<?> serviceInterfaceType) {
+        ServiceBeanNameBuilder serviceBeanNameBuilder = create(attributes, 
serviceInterfaceType, getEnvironment());
         return serviceBeanNameBuilder.build();
     }
 
-    private ReferenceBean buildReferenceBeanIfAbsent(String 
referencedBeanName, AnnotationAttributes attributes,
+    private ReferenceBean buildReferenceBeanIfAbsent(String referenceBeanName, 
AnnotationAttributes attributes,
                                                      Class<?> referencedType)
             throws Exception {
 
-        ReferenceBean<?> referenceBean = 
referenceBeanCache.get(referencedBeanName);
+        ReferenceBean<?> referenceBean = 
referenceBeanCache.get(referenceBeanName);
 
         if (referenceBean == null) {
             ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
                     .create(attributes, applicationContext)
                     .interfaceClass(referencedType);
             referenceBean = beanBuilder.build();
-            referenceBeanCache.put(referencedBeanName, referenceBean);
+            referenceBeanCache.put(referenceBeanName, referenceBean);
         } else if 
(!referencedType.isAssignableFrom(referenceBean.getInterfaceClass())) {
-            throw new IllegalArgumentException("reference bean name " + 
referencedBeanName + " has been duplicated, but interfaceClass " +
+            throw new IllegalArgumentException("reference bean name " + 
referenceBeanName + " has been duplicated, but interfaceClass " +
                     referenceBean.getInterfaceClass().getName() + " cannot be 
assigned to " + referencedType.getName());
         }
         return referenceBean;
diff --git 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
index d1a695f..af60e21 100644
--- 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
+++ 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
@@ -48,14 +48,14 @@ import static org.junit.Assert.assertTrue;
  */
 @RunWith(SpringRunner.class)
 @ContextConfiguration(
-    classes = {
-        ServiceAnnotationTestConfiguration.class,
-        ReferenceAnnotationBeanPostProcessorTest.class
-    })
+        classes = {
+                ServiceAnnotationTestConfiguration.class,
+                ReferenceAnnotationBeanPostProcessorTest.class
+        })
 @TestPropertySource(properties = {
-    "packagesToScan = 
org.apache.dubbo.config.spring.context.annotation.provider",
-    "consumer.version = ${demo.service.version}",
-    "consumer.url = dubbo://127.0.0.1:12345?version=2.5.7",
+        "packagesToScan = 
org.apache.dubbo.config.spring.context.annotation.provider",
+        "consumer.version = ${demo.service.version}",
+        "consumer.url = dubbo://127.0.0.1:12345?version=2.5.7",
 })
 public class ReferenceAnnotationBeanPostProcessorTest {
 
@@ -80,9 +80,14 @@ public class ReferenceAnnotationBeanPostProcessorTest {
     @Qualifier("helloServiceImpl")
     private HelloService helloServiceImpl;
 
+    // #4 ReferenceBean (Field Injection #2)
     @Reference(id = "helloService", methods = @Method(name = "sayName", 
timeout = 100))
     private HelloService helloService;
 
+    // #5 ReferenceBean (Field Injection #3)
+    @Reference
+    private HelloService helloService2;
+
     @Test
     public void test() throws Exception {
 
@@ -132,11 +137,11 @@ public class ReferenceAnnotationBeanPostProcessorTest {
     public void testGetReferenceBeans() {
 
         ReferenceAnnotationBeanPostProcessor beanPostProcessor = 
context.getBean(BEAN_NAME,
-            ReferenceAnnotationBeanPostProcessor.class);
+                ReferenceAnnotationBeanPostProcessor.class);
 
         Collection<ReferenceBean<?>> referenceBeans = 
beanPostProcessor.getReferenceBeans();
 
-        Assert.assertEquals(2, referenceBeans.size());
+        Assert.assertEquals(4, referenceBeans.size());
 
         ReferenceBean<?> referenceBean = referenceBeans.iterator().next();
 
@@ -148,19 +153,19 @@ public class ReferenceAnnotationBeanPostProcessorTest {
     public void testGetInjectedFieldReferenceBeanMap() {
 
         ReferenceAnnotationBeanPostProcessor beanPostProcessor = 
context.getBean(BEAN_NAME,
-            ReferenceAnnotationBeanPostProcessor.class);
+                ReferenceAnnotationBeanPostProcessor.class);
 
         Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> 
referenceBeanMap =
-            beanPostProcessor.getInjectedFieldReferenceBeanMap();
+                beanPostProcessor.getInjectedFieldReferenceBeanMap();
 
-        Assert.assertEquals(2, referenceBeanMap.size());
+        Assert.assertEquals(3, referenceBeanMap.size());
 
         for (Map.Entry<InjectionMetadata.InjectedElement, ReferenceBean<?>> 
entry : referenceBeanMap.entrySet()) {
 
             InjectionMetadata.InjectedElement injectedElement = entry.getKey();
 
             
Assert.assertEquals("org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedFieldElement",
-                injectedElement.getClass().getName());
+                    injectedElement.getClass().getName());
 
         }
 
@@ -170,10 +175,10 @@ public class ReferenceAnnotationBeanPostProcessorTest {
     public void testGetInjectedMethodReferenceBeanMap() {
 
         ReferenceAnnotationBeanPostProcessor beanPostProcessor = 
context.getBean(BEAN_NAME,
-            ReferenceAnnotationBeanPostProcessor.class);
+                ReferenceAnnotationBeanPostProcessor.class);
 
         Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> 
referenceBeanMap =
-            beanPostProcessor.getInjectedMethodReferenceBeanMap();
+                beanPostProcessor.getInjectedMethodReferenceBeanMap();
 
         Assert.assertEquals(2, referenceBeanMap.size());
 
@@ -182,7 +187,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
             InjectionMetadata.InjectedElement injectedElement = entry.getKey();
 
             
Assert.assertEquals("org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedMethodElement",
-                injectedElement.getClass().getName());
+                    injectedElement.getClass().getName());
 
         }
 
@@ -217,6 +222,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
             return demoServiceFromAncestor;
         }
 
+        // #1 ReferenceBean (Method Injection #1)
         @Reference(id = "my-reference-bean", version = "2.5.7", url = 
"dubbo://127.0.0.1:12345?version=2.5.7")
         public void setDemoServiceFromAncestor(DemoService 
demoServiceFromAncestor) {
             this.demoServiceFromAncestor = demoServiceFromAncestor;
@@ -230,6 +236,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
 
     private static class ParentBean extends AncestorBean {
 
+        // #2 ReferenceBean (Field Injection #1)
         @Reference(version = "${consumer.version}", url = "${consumer.url}")
         private DemoService demoServiceFromParent;
 
@@ -253,6 +260,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
             return demoService;
         }
 
+        // #3 ReferenceBean (Method Injection #2)
         @com.alibaba.dubbo.config.annotation.Reference(version = "2.5.7", url 
= "dubbo://127.0.0.1:12345?version=2.5.7")
         public void setDemoService(DemoService demoService) {
             this.demoService = demoService;
@@ -263,11 +271,11 @@ public class ReferenceAnnotationBeanPostProcessorTest {
     public void testReferenceBeansMethodAnnotation() {
 
         ReferenceAnnotationBeanPostProcessor beanPostProcessor = 
context.getBean(BEAN_NAME,
-            ReferenceAnnotationBeanPostProcessor.class);
+                ReferenceAnnotationBeanPostProcessor.class);
 
         Collection<ReferenceBean<?>> referenceBeans = 
beanPostProcessor.getReferenceBeans();
 
-        Assert.assertEquals(2, referenceBeans.size());
+        Assert.assertEquals(4, referenceBeans.size());
 
         ReferenceBean<?> referenceBean = referenceBeans.iterator().next();
 

Reply via email to