Skip to content

Commit 645152a

Browse files
author
kimi
committed
DUBBO-627 使用 JavaBeanSerializationUtil 实现泛化调用或泛化实现
1 parent 0e3b007 commit 645152a

File tree

6 files changed

+197
-14
lines changed

6 files changed

+197
-14
lines changed

dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,8 @@ public class Constants {
577577

578578
public static final String GENERIC_SERIALIZATION_DEFAULT = "true";
579579

580+
public static final String GENERIC_SERIALIZATION_BEAN = "bean";
581+
580582
/*
581583
* private Constants(){ }
582584
*/

dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanDescriptor.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@ public final class JavaBeanDescriptor implements Serializable, Iterable<Map.Entr
6161
*/
6262
private static final int TYPE_MIN = TYPE_CLASS;
6363

64-
private final String className;
64+
private String className;
6565

66-
private final int type;
66+
private int type;
6767

6868
private Map<Object, Object> properties = new LinkedHashMap<Object, Object>();
6969

70+
public JavaBeanDescriptor() {}
71+
7072
public JavaBeanDescriptor(String className, int type) {
7173
notEmpty(className, "class name is empty");
7274
if (!isValidType(type)) {
@@ -79,6 +81,14 @@ public JavaBeanDescriptor(String className, int type) {
7981
this.type = type;
8082
}
8183

84+
public void setClassName(String className) {
85+
this.className = className;
86+
}
87+
88+
public void setType(int type) {
89+
this.type = type;
90+
}
91+
8292
public boolean isClassType() {
8393
return TYPE_CLASS == type;
8494
}

dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/GenericServiceTest.java

Lines changed: 117 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@
2121
import java.util.HashMap;
2222
import java.util.List;
2323
import java.util.Map;
24+
import java.util.concurrent.atomic.AtomicReference;
2425

2526
import org.junit.Assert;
2627
import org.junit.Test;
2728

2829
import com.alibaba.dubbo.common.Constants;
30+
import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor;
31+
import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor;
32+
import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil;
2933
import com.alibaba.dubbo.common.extension.ExtensionLoader;
3034
import com.alibaba.dubbo.common.serialize.Serialization;
35+
import com.alibaba.dubbo.common.utils.ReflectUtils;
3136
import com.alibaba.dubbo.config.api.DemoException;
3237
import com.alibaba.dubbo.config.api.DemoService;
3338
import com.alibaba.dubbo.config.api.User;
@@ -37,11 +42,11 @@
3742

3843
/**
3944
* GenericServiceTest
40-
*
45+
*
4146
* @author william.liangf
4247
*/
4348
public class GenericServiceTest {
44-
49+
4550
@Test
4651
public void testGenericServiceException() {
4752
ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
@@ -50,8 +55,9 @@ public void testGenericServiceException() {
5055
service.setProtocol(new ProtocolConfig("dubbo", 29581));
5156
service.setInterface(DemoService.class.getName());
5257
service.setRef(new GenericService() {
58+
5359
public Object $invoke(String method, String[] parameterTypes, Object[] args)
54-
throws GenericException {
60+
throws GenericException {
5561
if ("sayName".equals(method)) {
5662
return "Generic " + args[0];
5763
}
@@ -117,7 +123,7 @@ public void testGenericReferenceException() {
117123
user.put("class", "com.alibaba.dubbo.config.api.User");
118124
user.put("name", "actual.provider");
119125
users.add(user);
120-
users = (List<Map<String, Object>>) genericService.$invoke("getUsers", new String[] {List.class.getName()}, new Object[] {users});
126+
users = (List<Map<String, Object>>) genericService.$invoke("getUsers", new String[]{List.class.getName()}, new Object[]{users});
121127
Assert.assertEquals(1, users.size());
122128
Assert.assertEquals("actual.provider", users.get(0).get("name"));
123129
} finally {
@@ -196,4 +202,111 @@ public void testGenericSerializationJava() throws Exception {
196202
}
197203
}
198204

205+
@Test
206+
public void testGenericInvokeWithBeanSerialization() throws Exception {
207+
ServiceConfig<DemoService> service = new ServiceConfig<DemoService>();
208+
service.setApplication(new ApplicationConfig("bean-provider"));
209+
service.setInterface(DemoService.class);
210+
service.setRegistry(new RegistryConfig("N/A"));
211+
DemoServiceImpl impl = new DemoServiceImpl();
212+
service.setRef(impl);
213+
service.setProtocol(new ProtocolConfig("dubbo", 29581));
214+
service.export();
215+
ReferenceConfig<GenericService> reference = null;
216+
try {
217+
reference = new ReferenceConfig<GenericService>();
218+
reference.setApplication(new ApplicationConfig("bean-consumer"));
219+
reference.setInterface(DemoService.class);
220+
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote");
221+
reference.setGeneric(Constants.GENERIC_SERIALIZATION_BEAN);
222+
GenericService genericService = reference.get();
223+
User user = new User();
224+
user.setName("zhangsan");
225+
List<User> users = new ArrayList<User>();
226+
users.add(user);
227+
Object result = genericService.$invoke("getUsers", new String[]{ReflectUtils.getName(List.class)}, new Object[]{JavaBeanSerializeUtil.serialize(users, JavaBeanAccessor.METHOD)});
228+
Assert.assertTrue(result instanceof JavaBeanDescriptor);
229+
JavaBeanDescriptor descriptor = (JavaBeanDescriptor) result;
230+
Assert.assertTrue(descriptor.isCollectionType());
231+
Assert.assertEquals(1, descriptor.propertySize());
232+
descriptor = (JavaBeanDescriptor) descriptor.getProperty(0);
233+
Assert.assertTrue(descriptor.isBeanType());
234+
Assert.assertEquals(user.getName(), ((JavaBeanDescriptor) descriptor.getProperty("name")).getPrimitiveProperty());
235+
} finally {
236+
if (reference != null) {
237+
reference.destroy();
238+
}
239+
service.unexport();
240+
}
241+
}
242+
243+
protected static class GenericParameter {
244+
245+
String method;
246+
247+
String[] parameterTypes;
248+
249+
Object[] arguments;
250+
}
251+
252+
@Test
253+
public void testGenericImplementationWithBeanSerialization() throws Exception {
254+
final AtomicReference reference = new AtomicReference();
255+
ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
256+
service.setApplication(new ApplicationConfig("bean-provider"));
257+
service.setRegistry(new RegistryConfig("N/A"));
258+
service.setProtocol(new ProtocolConfig("dubbo", 29581));
259+
service.setInterface(DemoService.class.getName());
260+
service.setRef(new GenericService() {
261+
262+
public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException {
263+
if ("getUsers".equals(method)) {
264+
GenericParameter arg = new GenericParameter();
265+
arg.method = method;
266+
arg.parameterTypes = parameterTypes;
267+
arg.arguments = args;
268+
reference.set(arg);
269+
return args[0];
270+
}
271+
return args;
272+
}
273+
});
274+
service.export();
275+
ReferenceConfig<DemoService> ref = null;
276+
try {
277+
ref = new ReferenceConfig<DemoService>();
278+
ref.setApplication(new ApplicationConfig("bean-consumer"));
279+
ref.setInterface(DemoService.class);
280+
ref.setUrl("dubbo://127.0.0.1:29581?scope=remote&generic=bean");
281+
DemoService demoService = ref.get();
282+
User user = new User();
283+
user.setName("zhangsan");
284+
List<User> users = new ArrayList<User>();
285+
users.add(user);
286+
List<User> result = demoService.getUsers(users);
287+
Assert.assertEquals(users.size(), result.size());
288+
Assert.assertEquals(user.getName(), result.get(0).getName());
289+
290+
GenericParameter gp = (GenericParameter)reference.get();
291+
Assert.assertEquals("getUsers", gp.method);
292+
Assert.assertEquals(1, gp.parameterTypes.length);
293+
Assert.assertEquals(ReflectUtils.getName(List.class), gp.parameterTypes[0]);
294+
Assert.assertEquals(1, gp.arguments.length);
295+
Assert.assertTrue(gp.arguments[0] instanceof JavaBeanDescriptor);
296+
JavaBeanDescriptor descriptor = (JavaBeanDescriptor)gp.arguments[0];
297+
Assert.assertTrue(descriptor.isCollectionType());
298+
Assert.assertEquals(ArrayList.class.getName(), descriptor.getClassName());
299+
Assert.assertEquals(1, descriptor.propertySize());
300+
descriptor = (JavaBeanDescriptor)descriptor.getProperty(0);
301+
Assert.assertTrue(descriptor.isBeanType());
302+
Assert.assertEquals(User.class.getName(), descriptor.getClassName());
303+
Assert.assertEquals(user.getName(), ((JavaBeanDescriptor)descriptor.getProperty("name")).getPrimitiveProperty());
304+
} finally {
305+
if (ref != null) {
306+
ref.destroy();
307+
}
308+
service.unexport();
309+
}
310+
}
311+
199312
}

dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import java.lang.reflect.Method;
2020

2121
import com.alibaba.dubbo.common.Constants;
22+
import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor;
23+
import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor;
24+
import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil;
2225
import com.alibaba.dubbo.common.extension.Activate;
2326
import com.alibaba.dubbo.common.extension.ExtensionLoader;
2427
import com.alibaba.dubbo.common.io.UnsafeByteArrayInputStream;
@@ -84,6 +87,21 @@ public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
8487
.append(args[i].getClass()).toString());
8588
}
8689
}
90+
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
91+
for(int i = 0; i < args.length; i++) {
92+
if (args[i] instanceof JavaBeanDescriptor) {
93+
args[i] = JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor)args[i]);
94+
} else {
95+
throw new RpcException(
96+
new StringBuilder(32)
97+
.append("Generic serialization [")
98+
.append(Constants.GENERIC_SERIALIZATION_BEAN)
99+
.append("] only support message type ")
100+
.append(JavaBeanDescriptor.class.getName())
101+
.append(" and your message type is ")
102+
.append(args[i].getClass().getName()).toString());
103+
}
104+
}
87105
}
88106
Result result = invoker.invoke(new RpcInvocation(method, args, inv.getAttachments()));
89107
if (result.hasException()
@@ -100,6 +118,8 @@ public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
100118
} catch (IOException e) {
101119
throw new RpcException("Serialize result failed.", e);
102120
}
121+
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
122+
return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
103123
} else {
104124
return new RpcResult(PojoUtils.generalize(result.getValue()));
105125
}

dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import java.lang.reflect.Method;
2121

2222
import com.alibaba.dubbo.common.Constants;
23+
import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor;
24+
import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor;
25+
import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil;
2326
import com.alibaba.dubbo.common.extension.Activate;
2427
import com.alibaba.dubbo.common.logger.Logger;
2528
import com.alibaba.dubbo.common.logger.LoggerFactory;
@@ -61,7 +64,16 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
6164
for (int i = 0; i < parameterTypes.length; i ++) {
6265
types[i] = ReflectUtils.getName(parameterTypes[i]);
6366
}
64-
Object[] args = PojoUtils.generalize(arguments);
67+
68+
Object[] args;
69+
if (ProtocolUtils.isBeanGenericSerialization(generic)) {
70+
args = new Object[arguments.length];
71+
for(int i = 0; i < arguments.length; i++) {
72+
args[i] = JavaBeanSerializeUtil.serialize(arguments[i], JavaBeanAccessor.METHOD);
73+
}
74+
} else {
75+
args = PojoUtils.generalize(arguments);
76+
}
6577

6678
invocation2.setMethodName(Constants.$INVOKE);
6779
invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
@@ -72,7 +84,22 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
7284
Object value = result.getValue();
7385
try {
7486
Method method = invoker.getInterface().getMethod(methodName, parameterTypes);
75-
return new RpcResult(PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType()));
87+
if (ProtocolUtils.isBeanGenericSerialization(generic)) {
88+
if (value instanceof JavaBeanDescriptor) {
89+
return new RpcResult(JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor)value));
90+
} else {
91+
throw new RpcException(
92+
new StringBuilder(64)
93+
.append("The type of result value is ")
94+
.append(value.getClass().getName())
95+
.append(" other than ")
96+
.append(JavaBeanDescriptor.class.getName())
97+
.append(", and the result is ")
98+
.append(value).toString());
99+
}
100+
} else {
101+
return new RpcResult(PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType()));
102+
}
76103
} catch (NoSuchMethodException e) {
77104
throw new RpcException(e.getMessage(), e);
78105
}
@@ -122,12 +149,18 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
122149
&& invocation.getArguments().length == 3
123150
&& ProtocolUtils.isGeneric(generic)) {
124151

152+
Object[] args = (Object[]) invocation.getArguments()[2];
125153
if (ProtocolUtils.isJavaGenericSerialization(generic)) {
126-
Object[] args = (Object[]) invocation.getArguments()[2];
127154

128155
for (Object arg : args) {
129156
if (!(byte[].class == arg.getClass())) {
130-
error(arg.getClass().getName());
157+
error(byte[].class.getName(), arg.getClass().getName());
158+
}
159+
}
160+
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
161+
for(Object arg : args) {
162+
if (!(arg instanceof JavaBeanDescriptor)) {
163+
error(JavaBeanDescriptor.class.getName(), arg.getClass().getName());
131164
}
132165
}
133166
}
@@ -138,15 +171,15 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
138171
return invoker.invoke(invocation);
139172
}
140173

141-
private void error(String type) throws RpcException {
174+
private void error(String expected, String actual) throws RpcException {
142175
throw new RpcException(
143176
new StringBuilder(32)
144177
.append("Generic serialization [")
145178
.append(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
146179
.append("] only support message type ")
147-
.append(byte[].class)
180+
.append(expected)
148181
.append(" and your message type is ")
149-
.append(type).toString());
182+
.append(actual).toString());
150183
}
151184

152185
}

dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/support/ProtocolUtils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ public static boolean isGeneric(String generic) {
3636
return generic != null
3737
&& !"".equals(generic)
3838
&& (Constants.GENERIC_SERIALIZATION_DEFAULT.equalsIgnoreCase(generic) /* 正常的泛化调用 */
39-
|| Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic)); /* 支持java序列化的流式泛化调用 */
39+
|| Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic) /* 支持java序列化的流式泛化调用 */
40+
|| Constants.GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic));
4041
}
4142

4243
public static boolean isDefaultGenericSerialization(String generic) {
@@ -48,4 +49,8 @@ public static boolean isJavaGenericSerialization(String generic) {
4849
return isGeneric(generic)
4950
&& Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic);
5051
}
52+
53+
public static boolean isBeanGenericSerialization(String generic) {
54+
return isGeneric(generic) && Constants.GENERIC_SERIALIZATION_BEAN.equals(generic);
55+
}
5156
}

0 commit comments

Comments
 (0)