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();