首先,我同意@df778899 他提供的解决方案是一个强大的解决方案。不过,如果您不想使用 spring 框架并且想进一步挖掘它,我会给您一个替代选择。
拦截器提供了强大而灵活的设计,包括调用监控、日志记录和消息路由。从某种意义上说,您正在寻找的关键价值是一种RMI级别的AOP(面向方面编程)支持
一般来说:
要求 RMI 直接支持这样的功能是不公平的
只是一个基本的远程方法调用原语,而 CORBA ORB 是
在接近 J2EE EJB (Enterprise JavaBean) 容器的层
优惠。在 CORBA 规范中,服务上下文直接
在 IIOP 级别(GIOP 或通用 Inter-Orb 协议)支持和
与 ORB 运行时集成。但是,对于 RMI/IIOP,这并不容易
让应用程序利用底层 IIOP 服务上下文
支持,即使协议层确实有这种支持。在
同时,当 RMI/JRMP(Java Remote
方法协议)被使用。因此,对于基于 RMI 的分布式
不使用或不必使用 ORB 或 EJB 的应用程序
容器环境,缺乏这样的能力限制了
可用的设计选择,尤其是当现有应用程序必须
扩展以支持新的基础设施级功能。修改
现有的 RMI 接口通常被证明是不可取的,因为
组件之间的依赖关系以及对客户端的巨大影响
应用程序。这种 RMI 限制的观察导致
我在本文中描述的通用解决方案
尽管如此
该解决方案基于 Java 反射技术和一些常见的
实现拦截器的方法。更重要的是,它定义了一个
可以轻松集成到任何基于 RMI 的架构
分布式应用程序设计。
下面的解决方案通过一个示例实现进行了演示,该示例实现支持使用 RMI 透明传递事务上下文数据,例如事务 ID (xid)。该解决方案包含以下三个重要组成部分:
- RMI远程接口命名-功能封装和拦截插件
- 服务上下文传播机制和服务器端接口支持
- 服务上下文数据结构和事务上下文传播支持
该实现假定使用了 RMI/IIOP。然而,它并没有
表示该解决方案仅适用于 RMI/IIOP。事实上,无论是
RMI/JRMP 或 RMI/IIOP 可用作底层 RMI 环境,
如果命名服务,甚至是两种环境的混合
两者都支持
命名函数封装
首先我们封装提供RMI远程的命名函数
接口查找,允许透明地插入拦截器
in. 这样的封装总是可取的,总是可以找到的
在大多数基于 RMI 的应用程序中。基础命名解析
机制在这里不是问题;它可以是任何支持 JNDI 的东西
(Java 命名和目录接口)。在这个例子中,为了使
代码更具说明性,我们假设所有服务器端远程 RMI
接口继承自一个标记远程接口ServiceInterface,
它本身继承自 Java RMI Remote 接口。数字
显示了类图,后面是我的代码 sn-ps
将进一步描述
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
}
}
}
}
您可以在以下指南here 中找到更多详细信息。如果你想从头开始,理解以上所有这些是很重要的,与 Spring-AOP Framework 健壮的解决方案相比。此外,我认为你会发现用于实现 an RmiClientInterceptor 的 Spring Framework 纯源代码非常有趣。再看看here。