关于远程调用(XFire/HttpInvoker/Hessian etc.)及远程服务管理的一些随想(中)

本文探讨了服务池的概念及其扩展模型,介绍了服务中心资源库如何动态注册和管理远程服务,以及服务自动注入的实现机制。通过Spring框架的支持,简化了远程服务的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

尽管服务池解决了一些问题,在某种程度上降低了复杂度,但仍存在如下一些问题:

        服务的运行期动态注册 <o:p></o:p>

        服务的自动注入( IoC<o:p></o:p>

        透明化服务 ID 的传递 <o:p></o:p>

<o:p> </o:p>

在服务池( ServicePool )概念的基础上进行扩展,我们得出了如下的系统模型:

 

 

 

在核心位置上是一个服务中心资源库( ServiceRepository ),存储了系统中用到的所有的远程服务。服务采取动态注册的机制,由对外提供的服务注册器( ServiceRegister )提供服务注册功能。外部系统可以实现该接口向资源中心注册服务。提供了一个启动时运行的注册器,可以把静态配置在系统中的服务都注册进来。 <o:p></o:p>

<o:p> </o:p>

       服务的生成、管理等均由服务中心自己维护,委托服务代理生成器( ServiceProxyGenerator )完成服务的创建。可以针对现有的远程调用方式,如 XFire,HttpInvoker,Hessian 等创建服务代理,也可以针对自己定义的远程调用方式创建服务代理,由 CustomServiceProxyGenerator 完成该功能。 <o:p></o:p>

       一个服务模型包括 5 个因素: <o:p></o:p>

        服务接口 serviceClass<o:p></o:p>

        服务 ID serviceId<o:p></o:p>

        服务类型 serviceType<o:p></o:p>

        服务地址 serviceUrl<o:p></o:p>

        附加属性 props<o:p></o:p>

查找一个服务需要两个因素,一个是服务接口,另一个是服务 ID 。这两个因素共同决定了一个服务,既服务中心内部的“服务 ID ”。通过这种方式,可以允许存在多个 ID 相同但接口不同的服务,也可以存在多个接口相同但 ID 不同的服务。 <o:p></o:p>

<o:p> </o:p>

服务 ID 的获取是系统中一个关键的功能,这部分对程序员来说应该是透明的,由系统自己维护。相应的提供了一个服务 ID 提供者 (ServiceIdProvider) 接口,由实现该接口的子类完成服务 ID 获取功能(这是比较关键的地方,需要特殊考虑)。 <o:p></o:p>

<o:p> </o:p>

对于程序员来说,使用服务中心里的服务再也不能比这样再简单了!看看配置:

xml 代码

 

  1. < bean id = "helloHttpInvokerService" parent = "abstractServiceProxyFactory" >    
  2.     < property name = "serviceInterface" >    
  3.         < value > com.tonysoft.common.service.repository.example.HelloHttpInvoker  value >    
  4.      property >    
  5.   bean >    

再看如何使用这个 bean  :

  1. private HelloHttpInvoker       helloHttpInvokerService ;    
  2. public void testHttpInvoker() {    
  3.         assertNotNull( "helloHttpInvokerService can't be null !" , helloHttpInvokerService );    
  4.         assertEquals ( "Hello , HttpInvoker !" , helloHttpInvokerService .sayHello());    
  5. }    
  6.     /**   
  7.      * @param helloHttpInvokerService   
  8.      *             the helloHttpInvokerService to set   
  9.      */    
  10.   
  11.     public void setHelloHttpInvokerService(HelloHttpInvoker helloHttpInvokerService) {    
  12.         this . helloHttpInvokerService = helloHttpInvokerService;    
  13.     }    

 

就是这样的简单! Spring 会把这个 bean 自动注入到程序中,可以象使用其他任何 bean 一样使用它!程序员完全不用关心该服务由谁提供、采用什么技术,他只要知道系统中存在这样一个服务就 OK 了。该技术彻底向程序员屏蔽了底层技术的实现细节,以统一的方式访问任何形式的远程服务。至于服务是如何生成、如何配置的将在后面叙述。 <o:p></o:p>

<o:p> </o:p>

服务( Service Bean )是如何实现自动注入( IoC )的呢? <o:p></o:p>

注意到上面配置的 bean 都继承了“ abstractServiceProxyFactory ”,它是一个工厂 bean ,负责根据给定的接口类型,到服务中心( ServiceRepository )查找服务,并生成服务代理。我们来看一下它的核心代码:

java 代码

 

 

  1. /**   
  2.   * 服务代理工厂。   
  3.   *   
  4.   * 

     

     
  5.   * 该工厂对程序员屏蔽了服务实现的技术细节,对于 XFire 、 Hessian 、 HttpInvoker 等常用远程服务形式进行封装。   
  6.   *   
  7.   * 

     

     
  8.   * 程序员只需要提供一个服务接口(契约),该工厂会从服务中心  ServiceRepository  中查找符合该接口的远程服务实例。   
  9.   *   
  10.   * 

     

     
  11.   * 查找的规则是由服务 ID 提供者所提供的服务 ID 和服务接口名字共同组成的服务关键字匹配。   
  12.   *   
  13.   * @author Tony   
  14.   */    
  15. public class ServiceProxyFactory implements FactoryBean {    
  16.   
  17.     /** 服务中心 */    
  18.     private ServiceRepository serviceRepository ;    
  19.   
  20.     /** 服务 ID 提供者 */    
  21.     private ServiceIdProvider serviceIdProvider ;    
  22.     /** 服务接口 */    
  23.     private Class             serviceInterface ;    
  24.     /**  
  25.      * @see org.springframework.beans.factory.FactoryBean#getObject()   
  26.      */    
  27.     public Object getObject() throws Exception {    
  28.         return ProxyFactory.getProxy(getObjectType(), new ServiceProxyInterceptor());    
  29. //        return serviceRepository.getService(serviceInterface, serviceIdProvider.getCurrentServiceId());    
  30.     }    
  31.     /**  
  32.      * @see org.springframework.beans.factory.FactoryBean#getObjectType()   
  33.      */    
  34.     public Class getObjectType() {    
  35.         return serviceInterface ;    
  36.     }    
  37.     /*   
  38.      * @see org.springframework.beans.factory.FactoryBean#isSingleton()   
  39.      */    
  40.     public boolean isSingleton() {    
  41.         return true ;    
  42.     }    
  43.     /*   
  44.      * 远程服务代理拦截器。   
  45.      */    
  46.     private class ServiceProxyInterceptor implements MethodInterceptor {    
  47.         /*   
  48.          * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)   
  49.          */    
  50.         public Object invoke(MethodInvocation invocation) throws Throwable {    
  51.             Method method = invocation.getMethod();    
  52.             Object[] args = invocation.getArguments();    
  53.             Object client = getClient();    
  54.             return method.invoke(client, args);    
  55.         }    
  56.         private Object getClient() {    
  57.             try {    
  58.                  return serviceRepository .getService( serviceInterface , serviceIdProvider .getCurrentServiceId());    
  59.             } catch (ServiceException e) {    
  60.                 // TODO    
  61.                 e.printStackTrace();    
  62.                 return null ;    
  63.             }    
  64.         }    
  65.     }    
  66.     // ---- 容器自动注入 ----    
  67.     ······   

 

真正的魅力就在这个地方。根据服务接口类型和服务 ID ,从服务中心获取特定的服务。服务接口是配置好的, 而服务 ID 则在运行时才能确定,根据不同的应用、不同的策略提供不同的 ServiceIdProvider 。其中用到了 SpringFactoryBean 和拦截器,至于为什么要在这里使用拦截器,可以参考 Spring 框架的源码。 <o:p></o:p>

<o:p> </o:p>

 

关于远程调用(XFire/HttpInvoker/Hessian etc.)及远程服务管理的一些随想(上)

关于远程调用(XFire/HttpInvoker/Hessian etc.)及远程服务管理的一些随想(下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值