You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by me...@apache.org on 2019/09/09 02:50:26 UTC

[dubbo] branch master updated: Polish #4674 & #4470 (#5033)

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 <me...@gmail.com>
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();