全部产品

泛化调用

更新时间:2020-02-18 16:40:48

在进行 RPC 调用时,应用无需依赖服务提供方的 Jar 包,只需要知道服务的接口名、方法名即可调用 RPC 服务。

泛化接口

  1. public interface GenericService {
  2. /**
  3. * 泛化调用仅支持方法参数为基本数据类型,
  4. * 或者方法参数类型在当前应用的 ClassLoader 中存在的情况
  5. *
  6. * @param methodName 调用方法名
  7. * @param args 调用参数列表
  8. * @return 调用结果
  9. * @throws com.alipay.sofa.rpc.core.exception.GenericException 调用异常
  10. */
  11. Object $invoke(String methodName, String[] argTypes, Object[] args) throws GenericException;
  12. /**
  13. * 支持参数类型无法在类加载器加载情况的泛化调用,对于非 JDK 类会序列化为 GenericObject
  14. *
  15. * @param methodName 调用方法名
  16. * @param argTypes 参数类型
  17. * @param args 方法参数,参数类型支持 GenericObject
  18. * @return result GenericObject 类型
  19. * @throws com.alipay.sofa.rpc.core.exception.GenericException
  20. */
  21. Object $genericInvoke(String methodName, String[] argTypes, Object[] args)
  22. throws GenericException;
  23. /**
  24. * 支持参数类型无法在类加载器加载情况的泛化调用
  25. *
  26. * @param methodName 调用方法名
  27. * @param argTypes 参数类型
  28. * @param args 方法参数,参数类型支持 GenericObject
  29. * @param context GenericContext
  30. * @return result GenericObject 类型
  31. * @throws com.alipay.sofa.rpc.core.exception.GenericException
  32. */
  33. Object $genericInvoke(String methodName, String[] argTypes, Object[] args,
  34. GenericContext context) throws GenericException;
  35. /**
  36. * 支持参数类型无法在类加载器加载情况的泛化调用,返回结果类型为 T
  37. *
  38. * @param methodName 调用方法名
  39. * @param argTypes 参数类型
  40. * @param args 方法参数,参数类型支持 GenericObject
  41. * @return result T 类型
  42. * @throws com.alipay.sofa.rpc.core.exception.GenericException
  43. */
  44. <T> T $genericInvoke(String methodName, String[] argTypes, Object[] args, Class<T> clazz) throws GenericException;
  45. /**
  46. * 支持参数类型无法在类加载器加载情况的泛化调用
  47. *
  48. * @param methodName 调用方法名
  49. * @param argTypes 参数类型
  50. * @param args 方法参数,参数类型支持 GenericObject
  51. * @param clazz 返回类型
  52. * @param context GenericContext
  53. * @return result T 类型
  54. * @throws com.alipay.sofa.rpc.core.exception.GenericException
  55. */
  56. <T> T $genericInvoke(String methodName, String[] argTypes, Object[] args, Class<T> clazz, GenericContext context) throws GenericException;
  57. }

$invoke 仅支持方法参数类型在当前应用的 ClassLoader 中存在的情况;$genericInvoke 支持方法参数类型在当前应用的 ClassLoader 中不存在的情况。

使用示例

Spring XML 配置:

  1. <!-- 引用 TR 服务 -->
  2. <sofa:reference interface="com.alipay.sofa.rpc.api.GenericService" id="genericService">
  3. <sofa:binding.tr>
  4. <sofa:global-attrs generic-interface="com.alipay.test.SampleService"/>
  5. </sofa:binding.tr>
  6. </sofa:reference>

Java 代码:

  1. /**
  2. * Java Bean
  3. */
  4. public class People {
  5. private String name;
  6. private int age;
  7. // getters and setters
  8. }
  9. /**
  10. * 服务方提供的接口
  11. */
  12. interface SampleService {
  13. String hello(String arg);
  14. People hello(People people);
  15. }
  1. /**
  2. * 消费方测试类
  3. */
  4. public class ConsumerClass {
  5. GenericService genericService;
  6. public void do() {
  7. // 1. $invoke 仅支持方法参数类型在当前应用的 ClassLoader 中存在的情况
  8. genericService.$invoke("hello", new String[]{ String.class.getName() }, new Object[]{"I'm an arg"});
  9. // 2. $genericInvoke 支持方法参数类型在当前应用的 ClassLoader 中不存在的情况。
  10. // 2.1 构造参数
  11. GenericObject genericObject = new GenericObject("com.alipay.sofa.rpc.test.generic.bean.People"); // 构造函数中指定全路径类名
  12. genericObject.putField("name", "Lilei"); // 调用 putField,指定field值
  13. genericObject.putField("age", 15);
  14. // 2.2 进行调用,不指定返回类型,返回结果类型为 GenericObject
  15. Object obj = genericService.$genericInvoke("hello", new String[]{"com.alipay.sofa.rpc.test.generic.bean.People"}, new Object[] { genericObject });
  16. Assert.assertTrue(obj.getClass() == GenericObject.class);
  17. // 2.3 进行调用,指定返回类型
  18. People people = genericService.$genericInvoke("hello", new String[]{"com.alipay.sofa.rpc.test.generic.bean.People"}, new Object[] { genericObject }, People.class);
  19. // 3. LDC 架构下的泛化调用使用
  20. // 3.1 构造 GenericContext 对象
  21. AlipayGenericContext genericContext = new AlipayGenericContext();
  22. genericContext.setUid("33");
  23. // 3.2 进行调用
  24. People people = genericService.$genericInvoke("hello", new String[] {"com.alipay.sofa.rpc.test.generic.bean.People"}, new Object[] { genericObject }, People.class, genericContext);
  25. }

特殊说明

调用 $genericInvoke(String methodName, String[] argTypes, Object[] args) 接口,会将除以下包以外的其他类序列化为 GenericObject

  1. "com.sun",
  2. "java",
  3. "javax",
  4. "org.ietf",
  5. "org.ogm",
  6. "org.w3c",
  7. "org.xml",
  8. "sunw.io",
  9. "sunw.util"