NotOnlyJava

http://www.ibm.com/developerworks/cn/java/j-lo-serial/
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Spring RMI的实现原理

Posted on 2013-07-22 14:03  NotOnlyJava  阅读(851)  评论(0编辑  收藏  举报
//客户端:

package com.service.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.concurrent.ConcurrentHashMap;

import com.service.export.RemoteMethodWapper;
import com.service.export.RemoteObject;

public class RMIClientBeanFactory implements InvocationHandler {

    private ConcurrentHashMap<Class<?>, ProxyAndRemoteBean> cache;

    public RMIClientBeanFactory() {
        cache = new ConcurrentHashMap<Class<?>, ProxyAndRemoteBean>();
    }

    /**
     * 获取远程对象
     * 
     * @param ins
     * @param url
     * @return
     */
    public Object getRemoteObject(Class<?> ins, String url) {
        if (!cache.contains(ins)) {
            try {
                Remote remote = Naming.lookup(url);
                Object proxy = Proxy.newProxyInstance(ins.getClassLoader(),new Class[] { ins }, this);
                ProxyAndRemoteBean bean = new ProxyAndRemoteBean(proxy, remote);
                cache.put(ins, bean);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (RemoteException e) {
                e.printStackTrace();
            } catch (NotBoundException e) {
                e.printStackTrace();
            }
        }
        return cache.get(ins).getProxy();
    }

    @Override
    public Object invoke(Object arg0, Method method, Object[] params)
            throws Throwable {
        System.out.println("[intercepter] call method:" + method.getName());
        Object obj = cache.get(method.getDeclaringClass());
        if (obj instanceof ProxyAndRemoteBean) {
            ProxyAndRemoteBean bean = (ProxyAndRemoteBean) obj;
            // 如果是框架的包转类型就把方法调用包装为MethodWapper再通过MethodWapper的RMIObjWaper的call调用
            Remote remote = bean.getRemote();
            if (remote instanceof RemoteObject) {
                RemoteObject objWaper = (RemoteObject) remote;
                RemoteMethodWapper mwp = new RemoteMethodWapper(method.getName(), params,method.getParameterTypes());
                return objWaper.call(mwp);
            } else {
                // 如果是远程对象是原生的Remote对象直接调用
                return method.invoke(remote, params);
            }
        }
        return null;
    }

    public void clear() {
        cache.clear();
    }

    /**
     * 包装了远程对象和本地代理对象
     * 
     * @author Czp
     * 
     */
    private static class ProxyAndRemoteBean {

        private Object proxy;

        private Remote remote;

        public ProxyAndRemoteBean(Object proxy, Remote remote) {
            super();
            this.proxy = proxy;
            this.remote = remote;
        }

        public Object getProxy() {
            return proxy;
        }

        public Remote getRemote() {
            return remote;
        }

    }
}
//

package com.service.export;

import java.io.Serializable;

public class RemoteMethodWapper implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private String method;
    
    private Object[] params;
    
    private Class<?>[] parTypes;

    
    
    public RemoteMethodWapper(String method, Object[] params, Class<?>[] parTypes) {
        this.method = method;
        this.params = params;
        this.parTypes = parTypes;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public Object[] getParams() {
        return params;
    }

    public void setParams(Object[] params) {
        this.params = params;
    }

    public Class<?>[] getParTypes() {
        return parTypes;
    }

    public void setParTypes(Class<?>[] parTypes) {
        this.parTypes = parTypes;
    }
    
    
}
//

package com.service.export;

import java.rmi.Remote;


public interface RemoteObject extends Remote{

    Object call(RemoteMethodWapper mwp) throws Exception;
}
//

package com.service.export;

import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;



public class RemoteObjetWapper extends UnicastRemoteObject implements RemoteObject {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    protected RemoteObjetWapper() throws RemoteException {
        super();
    }

    private Object target;



    public Object getTarget() {
        return target;
    }



    public void setTarget(Object target) {
        this.target = target;
    }



    @Override
    public Object call(RemoteMethodWapper mwp) throws Exception {
        String name = mwp.getMethod();
        Method m = this.target.getClass().getDeclaredMethod(name, mwp.getParTypes());
        return m.invoke(target, mwp.getParams());
    }



}
//

package com.service.export;


public interface ServiceExport {

    /**
     * 导出一个服务
     * 
     * @param remote 要导出的对象
     * @param serviceName 服务名称
     */
    void exportRMIObject(Object remote,String serviceName);
}
//

package com.service.export;

import java.net.Inet4Address;
import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

public class ServiceExportImpl implements ServiceExport {


    private String baseUrl;
    /**
     * 注册指定的端口
     * 
     * @param port
     */
    public ServiceExportImpl(int port) {
        try {
            LocateRegistry.createRegistry(port);
            baseUrl = "rmi://"+Inet4Address.getLocalHost().getHostAddress()+":"+port+"/";
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 导出一个服务对象
     * 
     */
    @Override
    public void exportRMIObject(Object remote, String name) {
        try {
            Remote rmiObj = getRMIObj(remote);
            Naming.rebind(baseUrl+ name, rmiObj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 如果要导出的对象没有实现remote则包装成
     * RemoteObjetWapper再导出
     * 
     * @param remote
     * @return
     * @throws RemoteException
     */
    private Remote getRMIObj(Object remote) throws RemoteException {
        if (remote instanceof Remote) {
            return (Remote) remote;
        } else {
            RemoteObjetWapper wapperImpl = new RemoteObjetWapper();
            wapperImpl.setTarget(remote);
            return wapperImpl;
        }
    }

}
//

package com.test;

public interface CommonService {

    String sayHello(String str);
}
//

package com.test;

import java.io.Serializable;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteService extends Remote {

    Serializable getObj(int i)throws RemoteException;
}
//

package com.test.impl;

import com.test.CommonService;

/**
 * 普通对象的实现不需要实现任何特定的接口,实现了
 * 对JDK RMI接口的解耦,方法不需要抛出特定的异常
 * 
 * @author Czp
 *
 */
public class CommonServiceImpl implements CommonService {

    @Override
    public String sayHello(String str) {
        System.out.println("from client:"+str);
        return "str"+str;
    }

}
//

package com.test.impl;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import com.test.RemoteService;

/**
 * 通过普通的RMI导出的服务实现类需要继承
 * UnicastRemoteObject 并且每个
 * 方法都需要抛出RemoteException
 * 
 * @author Czp
 *
 */
public class ServiceRemoteImpl extends UnicastRemoteObject implements RemoteService{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    protected ServiceRemoteImpl() throws RemoteException {
        
    }

    @Override
    public Serializable getObj(int i) throws RemoteException{
        System.out.println("ok:"+i);
        return "test:"+i;
    }

}
//

package com.test.impl;

import java.io.Serializable;

import com.service.client.RMIClientBeanFactory;
import com.test.CommonService;
import com.test.RemoteService;

public class TestClient {

    public static void main(String[] args) {
        try {
            RMIClientBeanFactory c = new RMIClientBeanFactory();
            
            //调用普通的远程对象
            String url = "rmi://10.148.144.77:6677/"+CommonService.class.getSimpleName();
            CommonService service = (CommonService) c.getRemoteObject(CommonService.class, url);
            String sayHello = service.sayHello("test");
            System.out.println("obj is:" + sayHello);
            
            //调用实现remote的远程对象与上面没有区别,框架做了透明处理
            String url2 = "rmi://10.148.144.77:6677/"+RemoteService.class.getSimpleName();
            RemoteService remote = (RemoteService) c.getRemoteObject(RemoteService.class, url2);
            Serializable rt = remote.getObj(10000);
            System.out.println(rt);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//

package com.test.impl;



import com.service.export.ServiceExport;
import com.service.export.ServiceExportImpl;
import com.test.CommonService;
import com.test.RemoteService;

public class TestService {

    public static void main(String[] args) throws Exception {
        ServiceExport export = new ServiceExportImpl(6677);
        
        //导出普通对象
        CommonService service = new CommonServiceImpl();
        export.exportRMIObject(service,CommonService.class.getSimpleName());
        System.out.println("export:"+CommonService.class.getSimpleName());
        
        //导出实现Remote的对象与上面没区别,框架做了透明处理
        RemoteService serviceRemote = new ServiceRemoteImpl();
        export.exportRMIObject(serviceRemote,RemoteService.class.getSimpleName());
        System.out.println("export:"+RemoteService.class.getSimpleName());
    }
}