Spring RMI 源码浅析-RmiProxyFactoryBean 调用服务
来源:互联网 发布:常用的数据挖掘软件 编辑:程序博客网 时间:2024/05/22 10:38
RmiProxyFactoryBean 定义
- public class RmiProxyFactoryBean extends RmiClientInterceptor implements FactoryBean, BeanClassLoaderAware {
- }
父类RmiClientInterceptor 定义
- public class RmiClientInterceptor extends RemoteInvocationBasedAccessor implements MethodInterceptor {
- //spring容器 bean实例化阶段 是否要 查找远程对象 预查找
- private boolean lookupStubOnStartup = true;
- //查找过的 远程对象是否进行缓存
- private boolean cacheStub = true;
- //如果连接失败 是否刷新远程调用stub
- private boolean refreshStubOnConnectFailure = false;
- //rmi客户端 套接字工厂
- private RMIClientSocketFactory registryClientSocketFactory;
- //缓存远程调用对象
- private Remote cachedStub;
- //查找远程对象时用到的监控器
- private final Object stubMonitor = new Object();
- //.....略
- }
一:查找远程服务对象
RmiProxyFactoryBean 是InitializingBean接口的实现 Spring容器在bean的实例化(getBean)阶段 回调afterPropertiesSet 来查找远程对象 然后 生成远程代理对象
- public void afterPropertiesSet() {
- //父类RmiClientInterceptor检查serviceUrl是否配置
- //父类RmiClientInterceptor 查找远程对象
- super.afterPropertiesSet();
- //远程调用接口检查
- if (getServiceInterface() == null) {
- throw new IllegalArgumentException("Property 'serviceInterface' is required");
- }
- //创建代理对象
- //因为父类RmiClientInterceptor实现了 MethodInterceptor 接口 所以this
- this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader());
- }
父类RmiClientInterceptor的 afterPropertiesSet 方法 干了两件事
1.验证是否配置了serviceUrl 如果没有 抛出异常
2.查找远程对象
- public void afterPropertiesSet() {
- //检查serviceUrl 属性是否为空 如果为空直接抛出异常
- super.afterPropertiesSet();
- //查找远程对象
- prepare();
- }
- public void prepare() throws RemoteLookupFailureException {
- //预查找远程对象 默认为true
- if (this.lookupStubOnStartup) {
- //通过标准Api 查找远程对象
- Remote remoteObj = lookupStub();
- //是否对stub进行缓存
- if (this.cacheStub) {
- this.cachedStub = remoteObj;
- }
- }
- }
通过java API查找远程对象
- protected Remote lookupStub() throws RemoteLookupFailureException {
- try {
- Remote stub = null;
- if (this.registryClientSocketFactory != null) {
- ...略 }
- else {
- //TODO 通过客户端配置 serviceUrl查找对象
- stub = Naming.lookup(getServiceUrl());
- }
- return stub;
- }
- catch (MalformedURLException ex) {
- throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex);
- }
- catch (NotBoundException ex) {
- throw new RemoteLookupFailureException(
- "Could not find RMI service [" + getServiceUrl() + "] in RMI registry", ex);
- }
- catch (RemoteException ex) {
- throw new RemoteLookupFailureException("Lookup of RMI stub failed", ex);
- }
- }
二:返回代理对象
RmiProxyFactoryBean是FactoryBean接口的实现 其返回的是getObject方法 返回的对象
- /**
- * 返回远程代理对象
- * 创建代理对象 是在afterPropertiesSet 方法完成
- */
- public Object getObject() {
- return this.serviceProxy;
- }
三:调用方法
父类实现了MethodInterceptor接口 在客户端调用方法时会被拦截
- public Object invoke(MethodInvocation invocation) throws Throwable {
- //获取远程对象 如果配置了缓存cacheStub=true 从缓存中获取 缓存中没有 现在立刻查找
- Remote stub = getStub();
- try {
- //TODO 客户端调用远程方法时 拦截处理
- return doInvoke(invocation, stub);
- }
- catch (RemoteConnectFailureException ex) {
- return handleRemoteConnectFailure(invocation, ex);
- }
- catch (RemoteException ex) {
- //如果是连接失败异常
- if (isConnectFailure(ex)) {
- //处理连接失败. 是否需要刷新
- return handleRemoteConnectFailure(invocation, ex);
- }
- else {
- throw ex;
- }
- }
- }
方法调用,如果是标准的Rmi 通过反射调用,非标准的交给doInvoke方法处理
- protected Object doInvoke(MethodInvocation invocation, Remote stub) throws Throwable {
- //spring RmiInvocationHandler包装的远程对象 非实现Remote接口的
- if (stub instanceof RmiInvocationHandler) {
- try {
- //不是标准的Rmi
- return doInvoke(invocation, (RmiInvocationHandler) stub);
- }
- //....略
- }
- else {
- //标准的java Rmi
- try {
- //直接通过反射调用
- return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, stub);
- }
- //....略
- }
- }
标准Rmi方法调用处理 RmiClientInterceptorUtils的 invokeRemoteMethod方法
- public static Object invokeRemoteMethod(MethodInvocation invocation, Object stub)
- throws InvocationTargetException {
- Method method = invocation.getMethod();
- try {
- if (method.getDeclaringClass().isInstance(stub)) {
- // directly implemented
- return method.invoke(stub, invocation.getArguments());
- }
- else {
- // not directly implemented
- Method stubMethod = stub.getClass().getMethod(method.getName(), method.getParameterTypes());
- return stubMethod.invoke(stub, invocation.getArguments());
- }
- }
- catch (InvocationTargetException ex) {
- throw ex;
- }
- catch (NoSuchMethodException ex) {
- throw new RemoteProxyFailureException("No matching RMI stub method found for: " + method, ex);
- }
- catch (Throwable ex) {
- throw new RemoteProxyFailureException("Invocation of RMI stub method failed: " + method, ex);
- }
- }
非标准Rmi处理 方法名 参数封装成InvocationHandler 通过中转站方法调用目标方法
- protected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler)
- throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- // 如果是toString方法
- if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
- return "RMI invoker proxy for service URL [" + getServiceUrl() + "]";
- }
- //invocationHandler spring包装过的Rmi远程对象 服务端在暴露服务时包装
- //createRemoteInvocation方法 返回RemoteInvocation实例 封装了方法调用相关信息 例如:参数, 方法名
- //Rmi服务端接受到信息后 会通过RemoteInvocation封装的信息 进行调用
- return invocationHandler.invoke(createRemoteInvocation(methodInvocation));
- }
RemoteInvocation定义
- public class RemoteInvocation implements Serializable {
- private String methodName;
- private Class[] parameterTypes;
- private Object[] arguments;
- private Map attributes;
- public RemoteInvocation(MethodInvocation methodInvocation) {
- this.methodName = methodInvocation.getMethod().getName();
- this.parameterTypes = methodInvocation.getMethod().getParameterTypes();
- this.arguments = methodInvocation.getArguments();
- }
- }
对于客户端方法调用 有两种形式
1、标准的Rmi 即实现了jdk Remote接口的 直接使用反射机制调用
2、非标准的Rmi spring暴露服务时包装成自己的对象[RmiInvocationHandler] 当客户段调用的时候 被拦截器拦截 封装方法名 参数等信息 最后调用RmiInvocationHandler的invoke方法 invoke方法类似中转站(泛化调用) 只要非标准Rmi 方法调用都会经过它调用目标方法。
- Spring RMI 源码浅析-RmiProxyFactoryBean 调用服务
- Spring RMI 源码浅析-RmiProxyFactoryBean 调用服务
- Spring RMI 源码浅析-RmiServiceExporter 导出服务
- 利用spring RMI 调用远程服务
- Spring RMI实现远程调用及源码
- 远程服务调用之RMI、Hessian、Burlap、Spring的HTTPinvoker
- Spring配置RMI服务
- Spring RMI暴露服务
- Spring RMI源码解读
- Spring RMI源码分析
- 远程调用 - spring+rmi
- Spring调用RMI
- Spring调用Rmi
- Java RMI远程服务调用
- dubbo源码浅析(五)-远程服务调用流程
- dubbo源码浅析(五)-远程服务调用流程
- SPRING RMI Remoting调用实例
- Spring中RMI的调用
- zookeeper C API实例
- Hibernate
- poj_1000 A+B Problem
- httpwebRequest多线程访问的时候提示“服务点数超过最大数目“
- iOS开发----FMDB的简单使用
- Spring RMI 源码浅析-RmiProxyFactoryBean 调用服务
- Flex的拖动事件 DragEvent DragManager
- WebCore中的渲染机制(一):基础知识
- VmPlayer 无法启动解决方法一例
- dwr 后台推送技术
- bash shell 123
- 菜鸟学JDBC(六)
- CDC::GetSafeHdc()和CDC::m_hDC的区别
- 如何进行性能测试需求细化