在进行 RPC 调用时,应用无需依赖服务提供方的 JAR 包,只需要知道服务的接口名、方法名即可调用 RPC 服务。
泛化接口
public interface GenericService{
/**
* 泛化调用仅支持方法参数为基本数据类型,或者方法参数类型在当前应用的 ClassLoader 中存在的情况。
*
* @param methodName 调用方法名。
* @param args 调用参数列表。
* @return 调用结果。
* @throws com.alipay.sofa.rpc.core.exception.GenericException 调用异常。
*/
Object $invoke(String methodName,String[] argTypes,Object[] args) throws GenericException;
/**
* 支持参数类型无法在类加载器加载情况的泛化调用,对于非 JDK 类会序列化为 GenericObject。
*
* @param methodName 调用方法名。
* @param argTypes 参数类型。
* @param args 方法参数,参数类型支持 GenericObject。
* @return result GenericObject 类型。
* @throws com.alipay.sofa.rpc.core.exception.GenericException
*/
Object $genericInvoke(String methodName,String[] argTypes,Object[] args)
throws GenericException;
/**
* 支持参数类型无法在类加载器加载情况的泛化调用。
*
* @param methodName 调用方法名。
* @param argTypes 参数类型。
* @param args 方法参数,参数类型支持 GenericObject。
* @param context GenericContext
* @return result GenericObject 类型。
* @throws com.alipay.sofa.rpc.core.exception.GenericException
*/
Object $genericInvoke(String methodName,String[] argTypes,Object[] args,
GenericContext context)throws GenericException;
/**
* 支持参数类型无法在类加载器加载情况的泛化调用,返回结果类型为 T。
*
* @param methodName 调用方法名。
* @param argTypes 参数类型。
* @param args 方法参数,参数类型支持 GenericObject。
* @return result T 类型。
* @throws com.alipay.sofa.rpc.core.exception.GenericException
*/
<T> T $genericInvoke(String methodName,String[] argTypes,Object[] args,Class<T> clazz) throws GenericException;
/**
* 支持参数类型无法在类加载器加载情况的泛化调用。
*
* @param methodName 调用方法名。
* @param argTypes 参数类型。
* @param args 方法参数,参数类型支持 GenericObject。
* @param clazz 返回类型。
* @param context GenericContext
* @return result T 类型。
* @throws com.alipay.sofa.rpc.core.exception.GenericException
*/
<T> T $genericInvoke(String methodName,String[] argTypes,Object[] args,Class<T> clazz,GenericContext context)throwsGenericException;
}
$invoke
仅支持方法参数类型在当前应用的 ClassLoader
中存在的情况;$genericInvoke
支持方法参数类型在当前应用的 ClassLoader
中不存在的情况。
使用示例
使用 Spring XML 创建泛化调用代理对象
<!-- 引用 TR 服务 --> <sofa:reference interface="com.alipay.sofa.rpc.api.GenericService" id="genericService"> <sofa:binding.tr> <sofa:global-attrs generic-interface="com.alipay.test.SampleService"/> </sofa:binding.tr> </sofa:reference>
Java 代码:
/** * Java Bean */ public class People{ private String name; private int age; // getters and setters } /** * 服务方提供的接口。 */ interface SampleService{ String hello(String arg); People hello(People people); }
/** * 消费方测试类。 */ public class ConsumerClass{ GenericService genericService; public void invokeTest(){ // 1. $invoke 仅支持方法参数类型在当前应用的 ClassLoader 中存在的情况。 genericService.$invoke("hello",new String[]{String.class.getName()},new Object[]{"I'm an arg"}); // 2. $genericInvoke 支持方法参数类型在当前应用的 ClassLoader 中不存在的情况。 // 2.1 构造参数 GenericObject genericObject =new GenericObject("com.alipay.sofa.rpc.test.generic.bean.People");// 构造函数中指定全路径类名。 genericObject.putField("name","Lilei");// 调用 putField,指定field值。 genericObject.putField("age",15); // 2.2 进行调用,不指定返回类型,返回结果类型为 GenericObject。 Object obj = genericService.$genericInvoke("hello",new String[]{"com.alipay.sofa.rpc.test.generic.bean.People"},new Object[]{ genericObject }); Assert.assertTrue(obj.getClass()==GenericObject.class); // 2.3 进行调用,指定返回类型。 People people = genericService.$genericInvoke("hello",new String[]{"com.alipay.sofa.rpc.test.generic.bean.People"},new Object[]{ genericObject },People.class); // 3. LDC 架构下的泛化调用使用。 // 3.1 构造 GenericContext 对象。 AlipayGenericContext genericContext =new AlipayGenericContext(); genericContext.setUid("33"); // 3.2 进行调用。 People people = genericService.$genericInvoke("hello",new String[]{"com.alipay.sofa.rpc.test.generic.bean.People"},new Object[]{ genericObject },People.class, genericContext); } }
使用 API 创建泛化调用代理对象
在非必要情况下,并不推荐项目中使用 API 方式创建泛化调用代理对象,建议您优先通过 Spring XML 进行创建。如果您无法使用 Spring XML 方式进行初始化,可考虑使用 API 方式进行创建。
使用 API 方式创建泛化调用代理时,需要注意以下事项:
泛化调用代理是比较重要的对象,不可放在交易中反复创建。
RPC 框架会检查是否有重复创建的情况,当相同配置的服务引用超过 3 次时,会产生异常,影响正常使用。
在应用启动过程中进行对象创建,通过异常中止、健康检查等方式确保项目启动时,代理对象已创建成功。
在应用退出前销毁泛化调用代理,实现优雅停止。
Java 代码:
@Component public class GenericServiceDemo implements InitializingBean, DisposableBean { private ConsumerConfig<GenericService> consumerConfig; private GenericService genericService; public GenericService getGenericService() { return genericService; } @Override public void afterPropertiesSet() throws Exception { this.consumerConfig = new ConsumerConfig<>(); RegistryConfig registryConfig = new RegistryConfig() .setProtocol("dsr"); consumerConfig.setGeneric(true) .setInterfaceId("com.alipay.test.SampleService") .setRegistry(registryConfig) .setProtocol("bolt") // 引用 Bolt 服务。 .setTimeout(5000); // 设置超时时间。 this.genericService = consumerConfig.refer(); } @Override public void destroy() throws Exception { if(this.consumerConfig != null) { consumerConfig.unRefer(); // 注销引用。 } } }
特殊说明
调用 $genericInvoke(String methodName, String[] argTypes, Object[] args)
接口,会将除以下包以外的其他类序列化为 GenericObject
。
"com.sun",
"java",
"javax",
"org.ietf",
"org.ogm",
"org.w3c",
"org.xml",
"sunw.io",
"sunw.util"
文档内容是否对您有帮助?