首先,我同意@df778899 他提供的解决方案是一个强大的解决方案。虽然,如果您不想使用 spring 框架并且想进一步挖掘它,我会给您一个替代选择。
拦截器提供了强大而灵活的设计,包括调用监控、日志记录和消息路由。从某种意义上说,您正在寻找的关键价值是一种RMI 级别的 AOP(面向方面的编程)支持
通常来说,一般来说:
要求 RMI 直接支持这些功能是不公平的,因为它只是一个基本的远程方法调用原语,而 CORBA ORB 处于接近 J2EE EJB(企业 JavaBean)容器所提供的层。在 CORBA 规范中,服务上下文在 IIOP 级别(GIOP,或通用 Orb 间协议)直接得到支持,并与 ORB 运行时集成。然而,对于 RMI/IIOP,应用程序利用底层 IIOP 服务上下文支持并不容易,即使协议层确实有这种支持。同时,当使用 RMI/JRMP(Java 远程方法协议)时,这种支持不可用。因此,对于不使用或不必使用 ORB 或 EJB 容器环境的基于 RMI 的分布式应用程序,缺乏此类功能限制了可用的设计选择,尤其是在必须扩展现有应用程序以支持新的基础设施级功能时。由于组件之间的依赖关系以及对客户端应用程序的巨大影响,修改现有 RMI 接口通常被证明是不可取的。对这种 RMI 限制的观察导致了我在本文中描述的通用解决方案
尽管以上所有
该解决方案基于 Java 反射技术和一些实现拦截器的常用方法。更重要的是,它定义了一个可以轻松集成到任何基于 RMI 的分布式应用程序设计中的架构。
下面的解决方案通过一个示例实现来演示,该示例实现支持使用 RMI 透明传递事务上下文数据,例如事务 ID (xid)。该解决方案包含以下三个重要组件:
- RMI远程接口命名-功能封装和拦截插件
- 服务上下文传播机制和服务器端接口支持
- 服务上下文数据结构和事务上下文传播支持
该实现假定使用了 RMI/IIOP。但是,这绝不意味着该解决方案仅适用于 RMI/IIOP。事实上,RMI/JRMP 或 RMI/IIOP 都可以用作底层 RMI 环境,如果命名服务同时支持这两种环境,甚至可以混合使用这两种环境
命名函数封装
首先,我们封装提供 RMI 远程接口查找的命名函数,允许透明地插入拦截器。这样的封装总是可取的,并且总是可以在大多数基于 RMI 的应用程序中找到。底层的命名解析机制在这里不是问题;它可以是任何支持 JNDI(Java 命名和目录接口)的东西。在这个例子中,为了使代码更具有说明性,我们假设所有服务器端远程 RMI 接口都继承自一个标记远程接口 ServiceInterface,该接口本身继承自 Java RMI Remote 接口。图显示了类图,后面是我将进一步描述的代码片段
RMI 调用拦截器
要启用调用拦截器,从 RMI 命名服务获取的原始 RMI 存根引用必须由本地代理包装。为了提供通用实现,使用 Java 动态代理 API 来实现这样的代理。在运行时,会创建一个代理实例;它实现了与包装的存根引用相同的 ServiceInterface RMI 接口。在第一次被拦截器处理之后,任何调用最终都会被委托给存根。RMI 拦截器工厂的简单实现如下图所示的类图
package rmicontext.interceptor;
public interface ServiceInterfaceInterceptorFactoryInterface {
ServiceInterface newInterceptor(ServiceInterface serviceStub, Class serviceInterfaceClass) throws Exception;
}
package rmicontext.interceptor;
public class ServiceInterfaceInterceptorFactory
implements ServiceInterfaceInterceptorFactoryInterface {
public ServiceInterface newInterceptor(ServiceInterface serviceStub, Class serviceInterfaceClass)
throws Exception {
ServiceInterface interceptor = (ServiceInterface)
Proxy.newProxyInstance(serviceInterfaceClass.getClassLoader(),
new Class[]{serviceInterfaceClass},
new ServiceContextPropagationInterceptor(serviceStub)); // ClassCastException
return interceptor;
}
}
package rmicontext.interceptor;
public class ServiceContextPropagationInterceptor
implements InvocationHandler {
/**
* The delegation stub reference of the original service interface.
*/
private ServiceInterface serviceStub;
/**
* The delegation stub reference of the service interceptor remote interface.
*/
private ServiceInterceptorRemoteInterface interceptorRemote;
/**
* Constructor.
*
* @param serviceStub The delegation target RMI reference
* @throws ClassCastException as a specified uncaught exception
*/
public ServiceContextPropagationInterceptor(ServiceInterface serviceStub)
throws ClassCastException {
this.serviceStub = serviceStub;
interceptorRemote = (ServiceInterceptorRemoteInterface)
PortableRemoteObject.narrow(serviceStub, ServiceInterceptorRemoteInterface.class);
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
// Skip it for now ...
}
}
为了完成ServiceManager类,实现了一个简单的接口代理缓存:
package rmicontext.service;
public class ServiceManager
implements ServiceManagerInterface {
/**
* The interceptor stub reference cache.
* <br><br>
* The key is the specific serviceInterface sub-class and the value is the interceptor stub reference.
*/
private transient HashMap serviceInterfaceInterceptorMap = new HashMap();
/**
* Gets a reference to a service interface.
*
* @param serviceInterfaceClassName The full class name of the requested interface
* @return selected service interface
*/
public ServiceInterface getServiceInterface(String serviceInterfaceClassName) {
// The actual naming lookup is skipped here.
ServiceInterface serviceInterface = ...;
synchronized (serviceInterfaceInterceptorMap) {
if (serviceInterfaceInterceptorMap.containsKey(serviceInterfaceClassName)) {
WeakReference ref = (WeakReference) serviceInterfaceInterceptorMap.get(serviceInterfaceClassName);
if (ref.get() != null) {
return (ServiceInterface) ref.get();
}
}
try {
Class serviceInterfaceClass = Class.forName(serviceInterfaceClassName);
ServiceInterface serviceStub =
(ServiceInterface) PortableRemoteObject.narrow(serviceInterface, serviceInterfaceClass);
ServiceInterfaceInterceptorFactoryInterface factory = ServiceInterfaceInterceptorFactory.getInstance();
ServiceInterface serviceInterceptor =
factory.newInterceptor(serviceStub, serviceInterfaceClass);
WeakReference ref = new WeakReference(serviceInterceptor);
serviceInterfaceInterceptorMap.put(serviceInterfaceClassName, ref);
return serviceInterceptor;
} catch (Exception ex) {
return serviceInterface; // no interceptor
}
}
}
}
您可以在此处的以下指南中找到更多详细信息。与 Spring-AOP Framework 健壮的解决方案相比,如果您希望从头开始,了解以上所有内容非常重要。此外,我认为您会发现 Spring Framework 的纯源代码实现非常有趣an RmiClientInterceptor
。再看看这里。