java的RMI

需要实现remote接口

  • 下面我来演示一个 规范的 开发RMI接口的方法规范
package com.czxy.mapreduce.demo01;
import	java.rmi.RemoteException;

import java.rmi.Remote;

/**
 * @author 550894211@qq.com
 * @version v 1.0
 * @date 2019/12/31
 * 远程过程调用必须声明为 public
 * 远程过程必须继承自 java.rmi.Remote
 */
public interface RMIQueryStatus extends Remote {
    /**
    * 远程接口中的函数必须将java.rmi.RemoteException声明于其throws子句中
    * */
    RMIQueryStatus getStatus() throws RemoteException;
}
如何获得本地存根对象

客户端如果要访问一个远程对象,必须获得一个本地的存根对象,java引用了RMI远程对象注册点(registry)解决了这个问题

注意

JDK 5.0版本以前,用户需奏通过rmic工具生成客户端存根,在夏.早的Java版本
JDK1.1中,服务専膏兼也必須由rmic产生。
Hadoop源码剖析08-java远程过程调用(二)_反射

java动态代理

从包和类名可以知道,java.lang.reflect.Proxy和Java反射有关,同时也和代理模式有关.
代理(Proxy)在《现代汉语词典》里的解释是:受当事人委托,代表他进行某种活动,如
贸易、诉讼、纳税、签订合同等。如果把这个解释应用到面向对象领域,应垓是:代理对象,
代表另一个对象(目标对象,Target),执行相关活动。也就是说,在实际应用中使用代理对
象作为中介,代替目标对象.

代理对象的两个重要任务

  • 实现代理接口
  • 调用转发
    上面两点,缺一不可

proxy接口

package com.czxy.mapreduce.demo01;

import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;

import java.lang.reflect.Proxy;

/**
 * @author 550894211@qq.com
 * @version v 1.0
 * @date 2019/12/31
 */
public class demo {
   /**
     *返回代理类的{@code java.lang.Class}对象
     *给定一个类加载器和一个接口数组。代理类
     *将由指定的类加载器定义并实现
     *所有提供的接口。如果有任何给定的接口
     *是非公开的,代理类将是非公开的。如果是代理类
     *对于接口的相同排列,已经由
     *类加载器,然后将返回现有的代理类;除此以外,
     *这些接口的代理类将动态生成
     *并由类加载器定义。
     *
     * <p>可能对参数有一些限制
     *传递给{@code Proxy.getProxyClass}:
     *
     * <ul>
     * <li>所有{@code Class}对象
     * {@code interfaces}数组必须表示接口,而不是
     *类或原始类型。
     *
     * <li> {@ code interfaces}数组中不能有两个元素
     * 指相同的{@code Class}对象。
     *
     * <li>所有接口类型必须通过名称按名称可见
     *指定的类加载器。换句话说,对于类加载器
     * {@code cl}和每个接口{@code i},以下
     *表达式必须为真:
     * <pre>
     * Class.forName(i.getName(),false,cl)==我
     * </ pre>
     *
     * <li>所有非公共接口必须位于同一程序包中;
     *否则,代理类将无法
     *实现所有接口,而不管它是什么包
     *定义于。
     *
     * <li>对于指定接口的任何成员方法集
     *具有相同签名:
     * <ul>
     * <li>如果任何方法的返回类型是原始类型
     *类型或无效,则所有方法必须具有相同的
     *返回类型。
     * <li>否则,方法之一必须具有返回类型,该返回类型应为
     *可分配给其余部分的所有返回类型
     * 方法。
     * </ ul>
     *
     * <li>生成的代理类不得超过任何限制
     *在虚拟机的类上。例如,虚拟机可能会限制
     *一个类可以实现的接口数量为65535;在
     *在这种情况下,{@ code interfaces}数组的大小不得
     *超过65535。
     * </ ul>
     *
     * <p>如果违反了任何这些限制,
     * {@code Proxy.getProxyClass}将抛出一个
     * {@code IllegalArgumentException}。如果{@code接口}
     *数组参数或其任何元素为{@code null},
     * {@code NullPointerException}将被抛出。
     *
     * <p>请注意,指定代理接口的顺序为
     *重大:具有相同组合的两个代理类请求
     *接口,但顺序不同将导致两个不同
     *代理类。
     *
     * @param loader类加载器定义代理类
     * @param interfaces代理类的接口列表
     *实施
     * @返回在指定的类加载器中定义的代理类
     *并实现指定的接口
     * @throws IllegalArgumentException如果对
     *可能传递给{@code getProxyClass}的参数
     *被违反
     * @throws SecurityException如果存在安全管理器<em> s </ em>
     *并且满足以下任何条件:
     * <ul>
     * <li>给定的{@code loader}为{@code null},
     *调用者的类加载器不是{@code null},并且
     *调用{@link SecurityManager#checkPermission
     * s.checkPermission}与
     * {@code RuntimePermission(“ getClassLoader”)}权限
     *拒绝访问。</ li>
     * <li>每个代理接口{@code intf},
     *调用者的类加载器与或
     * {@code intf}的类加载器的祖先,并且
     *调用{@link SecurityManager#checkPackageAccess
     * s.checkPackageAccess()}拒绝访问{@code intf}。</ li>
     * </ ul>
     *如果{@code interfaces}数组,则抛出NullPointerException
     *参数或其任何元素均为{@code null}
     */
   //获取代理类的class对象
    @CallerSensitive
    public static Class<?> getProxyClass(ClassLoader loader,
                                         Class<?>... interfaces)
            throws IllegalArgumentException
    {
        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        return getProxyClass0(loader, intfs);
    }
}

调用转发 java.lang.reflect.Invocationhandeler

这个接口中只有一个方法

 /**
     * 
     * @param proxy 代理对象本身
     * @param method 调用的代理对象上的方法
     * @param args 传递给该方法的参数
     * @return  结果
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;

Hadoop源码剖析08-java远程过程调用(二)_hdfs_02