• Spring RMI的实现原理


    //客户端:
    
    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());
        }
    }
  • 相关阅读:
    汉斯·季默:布拉格现场
    天使在美国第二部:重建
    欢迎访问我的独立博客 tracefact.net (2019.1.30)
    Kafka 分布式消息系统
    Webpack入门
    《.NET之美》消息及勘误
    MacBook笔记本微信视频聊天没有声音怎么办?
    libnuma.so.1()(64bit) is needed by mysql-community-server-5.7.9-1.el6.x86_64
    List stream 对象 属性去重
    JS遍历对象的方式
  • 原文地址:https://www.cnblogs.com/czpblog/p/3167991.html
Copyright © 2020-2023  润新知