论坛首页 Java企业应用论坛

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

浏览 5783 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-03-18  

 

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

*         服务的运行期动态注册 <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 。其中用到了 Spring FactoryBean 和拦截器,至于为什么要在这里使用拦截器,可以参考 Spring 框架的源码。 <o:p></o:p>

<o:p> </o:p>

 

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

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

   发表时间:2007-03-18  
LZ你用的VP Suite是企业版吗?能否给我一个license?
wang.ming@shixintech.com
0 请登录后投票
   发表时间:2007-03-18  
确实是好文,J2EE的远程调用一直困扰着一些程序员,看了这篇文章后感觉不再那么可怕了.
0 请登录后投票
   发表时间:2007-03-19  
mingisme 写道
LZ你用的VP Suite是企业版吗?能否给我一个license?
wang.ming@shixintech.com


我用的是社区版,图片是用工具截下来的:)
截图工具是“FastStone Capture”,非常好用。
0 请登录后投票
   发表时间:2007-03-19  
ecsoftcn 写道
mingisme 写道
LZ你用的VP Suite是企业版吗?能否给我一个license?
wang.ming@shixintech.com


我用的是社区版,图片是用工具截下来的:)
截图工具是“FastStone Capture”,非常好用。


谢谢了。社区版的导出图片背景图里有community edition等字样,不爽。另外整理word和pdf等功能也限制了。有个enterprise版就爽了。
0 请登录后投票
   发表时间:2007-03-19  
ws俺不是很清楚

但好像越看越像uddi+spring...
0 请登录后投票
   发表时间:2007-03-28  
不错,学习中。。。。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics