实现RMI(远程方法调用)的步骤:
引用
---------------------------------------------------------------
一、定义远程服务接口,扩展java.rmi.Remote。
二、实现远程服务具体类,继承java.rmi.UnicastRemoteObject类。
三、利用rmic生成Stub和Skeleton类,在JDK5.0中使用了动态代理,不需要生成任何类。
四、启动RMI注册表(rmiregistry)。
五、启动远程服务,即将远程服务具体类注册到RMI注册表中。
六、调用远程服务。
---------------------------------------------------------------
一、定义远程服务接口,扩展java.rmi.Remote。
二、实现远程服务具体类,继承java.rmi.UnicastRemoteObject类。
三、利用rmic生成Stub和Skeleton类,在JDK5.0中使用了动态代理,不需要生成任何类。
四、启动RMI注册表(rmiregistry)。
五、启动远程服务,即将远程服务具体类注册到RMI注册表中。
六、调用远程服务。
---------------------------------------------------------------
使用RMI常犯的三个错误:
引用
---------------------------------------------------------------
一、忘了在启动远程服务之前先启动RMI注册表(要用Naming.rebind()注册服务,rmiregistry必须是运行的)。
二、忘了将变量和返回值的类型转为可序列化的类型(这种错误无法在编译期发现,只会在运行时发现)。
三、忘了给客户端提供Stub类。
---------------------------------------------------------------
一、忘了在启动远程服务之前先启动RMI注册表(要用Naming.rebind()注册服务,rmiregistry必须是运行的)。
二、忘了将变量和返回值的类型转为可序列化的类型(这种错误无法在编译期发现,只会在运行时发现)。
三、忘了给客户端提供Stub类。
---------------------------------------------------------------
*transient关键字可以让JVM在序列化对象时忽略这个变量。
代理模式:为另一个对象提供替身或占位符以控制对这个对象的访问。
*使用代理模式创建代表(Representative)对象,让代表对象控制某对象的访问。被代理的对象可以是远程对象、创建开销大的对象或者需要安全控制的对象。
*远程代理是一般代理模式的一种实现。
代理模式有很多变种,几乎都与控制访问有关,它控制访问的几种方式:
引用
---------------------------------------------------------------
一、远程代理控制远程对象的访问。
二、虚拟代理控制创建开销大的资源的访问。
三、保护代理基于权限控制对资源的访问。
---------------------------------------------------------------
一、远程代理控制远程对象的访问。
二、虚拟代理控制创建开销大的资源的访问。
三、保护代理基于权限控制对资源的访问。
---------------------------------------------------------------
*远程代理(Remote Proxy)模式:可以作为另一个JVM上对象的本地代表。调用代理的方法会被代理利用网络转发到远程执行,并且结果会通过网络返回给代理,再由代理将结果转给客户。
*虚拟代理(Virtual Proxy)模式:作为创建开销大的对象的代表。虚拟代理经常在我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由代理来扮演它的替身。对象创建后,代理就会将请求直接委托给对象。
设计谜题
---------------------------------------------------------------
使用第十章的状态(State)模式对ImageProxy类进行重新设计。
---------------------------------------------------------------
*动态代理:Java在java.lang.reflect包中有自己的代理支持。利用这个包你可以在运行时动态地创建代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。因为实际的代理类是在运行时创建的,因此称这项Java技术为动态代理。
NonOwnerInvocationHandler代码:
--------------------------------------------------------------- import java.lang.reflect.*; public class NonOwnerInvocationHandler implements InvocationHandler { PersonBean person; public NonOwnerInvocationHandler(PersonBean person){ this.person = person; } public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException{ try{ if(method.getName().startsWith("get")){ return method.invoke(person,args); }else if(method.getName().equals("setHotOrNotRating")){ return method.invoke(person,args); }else if(method.getName().startsWith("set")){ throw new IllegalAccessException(); } } catch (InvocationTargetException e){ e.printStackTrace(); } return null; } } ---------------------------------------------------------------
Sharpen your pencil解答:
--------------------------------------------------------------- PersonBean getNonOwnerProxy(PersonBean person){ return (PersonBean)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new NonOwnerInvocationHandler()); } PersonBean getProxy(PersonBean person,InvocationHandler handler){ if(handler instanceof OwnerInvocationHandler){ return getOwnerProxy(person); }else if(handler instanceof NonOwnerInvocationHandler){ return getNonOwnerProxy(person); } } ---------------------------------------------------------------
连连看解答:
引用
---------------------------------------------------------------
装饰者(Decorator)模式-->包装另一个对象,并提供额外的行为。
外观(Facade)模式-->包装许多对象以简化它们的接口。
代理(Proxy)模式-->包装另一个对象,并控制对它的访问。
适配器(Adapter)模式-->包装另一个对象,并提供不同的接口。
---------------------------------------------------------------
装饰者(Decorator)模式-->包装另一个对象,并提供额外的行为。
外观(Facade)模式-->包装许多对象以简化它们的接口。
代理(Proxy)模式-->包装另一个对象,并控制对它的访问。
适配器(Adapter)模式-->包装另一个对象,并提供不同的接口。
---------------------------------------------------------------
其他种类的代理:
引用
---------------------------------------------------------------
一、防火墙代理(Firewall Proxy):控制网络资源的访问,保护资源免受“坏客户”的侵害。
二、只能引用代理(Smart Reference Proxy):当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
三、缓存代理(Caching Proxy):为开销大的计算结果提供暂时存储。它允许多个客户共享结果以减少计算或网络延迟。
四、同步代理(Synchronization Proxy):在多线程的情况下为主题提供安全的访问。
五、复杂隐藏代理(Complexity Hiding Proxy):用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也成为外观代理(Facade Proxy)。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。
六、写入时复制代理(Copy-On-Write Proxy):用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止,这是虚拟代理的变体。
---------------------------------------------------------------
一、防火墙代理(Firewall Proxy):控制网络资源的访问,保护资源免受“坏客户”的侵害。
二、只能引用代理(Smart Reference Proxy):当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
三、缓存代理(Caching Proxy):为开销大的计算结果提供暂时存储。它允许多个客户共享结果以减少计算或网络延迟。
四、同步代理(Synchronization Proxy):在多线程的情况下为主题提供安全的访问。
五、复杂隐藏代理(Complexity Hiding Proxy):用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也成为外观代理(Facade Proxy)。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。
六、写入时复制代理(Copy-On-Write Proxy):用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止,这是虚拟代理的变体。
---------------------------------------------------------------
2、代理(Proxy)模式小结
*代理模式为另一个对象提供代表,以便控制客户对对象的访问,管理访问的方式有许多种。
*远程代理管理客户和远程对象之间的交互。
*虚拟代理控制访问实例化开销大的对象。
*保护模式基于调用者控制对对象方法的访问。
*代理模式有许多变体,例如:缓存代理、同步代理、防火墙代理与写入时复制代理。
*代理在结构上类似装饰者,但是目的不同。
*装饰者模式为对象加上行为,而代理控制访问。
*Java内置的代理支持,可以根据需要动态创建代理,并将所有调用分配到所选的处理器。
*和其它的包装者(wrapper)一样,代理会造成你的设计中类的数目的增加。
3、RMI(远程方法调用)实例
/** * 远程接口 * * @author zangweiren 2010-4-8 * */ public interface HelloRemote extends Remote { String sayHello() throws RemoteException; } /** * 远程服务实现类 * * @author zangweiren 2010-4-8 * */ public class HelloImpl extends UnicastRemoteObject implements HelloRemote { private static final long serialVersionUID = -5554845400316615009L; public static void main(String[] args) { try { HelloRemote helloRemote = new HelloImpl(); Naming.rebind("HelloRemote", helloRemote); } catch (RemoteException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } } public HelloImpl() throws RemoteException { } @Override public String sayHello() throws RemoteException { return "Hello,world.I am zangweiren."; } } /** * 远程服务客户端 * * @author zangweiren 2010-4-8 * */ public class HelloClient { public static void main(String[] args) { try { HelloRemote helloRemote = (HelloRemote) Naming .lookup("rmi://127.0.0.1/HelloRemote"); String words = helloRemote.sayHello(); System.out.println(words); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } } }
4、远程代理(Remote Proxy)模式实例
/** * 服务器远程接口 * * @author zangweiren 2010-4-8 * */ public interface ServerRemote extends Remote { void shutdown() throws RemoteException; void startup() throws RemoteException; } /** * 服务器实现类 * * @author zangweiren 2010-4-8 * */ public class ServerImpl extends UnicastRemoteObject implements ServerRemote { private static final long serialVersionUID = -1466325816915299894L; public static void main(String[] args) { ServerRemote server; try { server = new ServerImpl(); Naming.rebind("ServerRemote", server); } catch (RemoteException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } } public ServerImpl() throws RemoteException { } @Override public void shutdown() throws RemoteException { System.out.println("The server is shutdown."); } @Override public void startup() throws RemoteException { System.out.println("The server is running..."); } } /** * 远程代理客户端测试程序 * * @author zangweiren 2010-4-8 * */ public class TestServer { public static void main(String[] args) { try { ServerRemote server = (ServerRemote) Naming.lookup("ServerRemote"); server.startup(); server.shutdown(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } } }
测试结果:
引用
The server is running...
The server is shutdown.
The server is shutdown.
5、虚拟代理(Virtual Proxy)模式实例(结合了状态模式)
/** * 视频播放器 * * @author zangweiren 2010-4-8 * */ public interface MediaPlayer { int getHeight(); int getWidth(); void play(); } /** * 视频播放器实现类 * * @author zangweiren 2010-4-8 * */ public class MediaPlayerImpl implements MediaPlayer { @Override public int getHeight() { return 1024; } @Override public int getWidth() { return 768; } @Override public void play() { System.out.println("The vedio is playing..."); } } /** * 视频播放器状态 * * @author zangweiren 2010-4-8 * */ public interface MediaPlayerState extends MediaPlayer { } /** * 未加载状态 * * @author zangweiren 2010-4-8 * */ public class NotLoadedState implements MediaPlayerState { private MediaPlayerProxy player; public NotLoadedState(MediaPlayerProxy player) { this.player = player; } @Override public int getHeight() { return 800; } @Override public int getWidth() { return 600; } @Override public void play() { player.setState(player.getLoadingState()); player.play(); } } /** * 加载中状态 * * @author zangweiren 2010-4-8 * */ public class LoadingState implements MediaPlayerState { private MediaPlayerProxy player; public LoadingState(MediaPlayerProxy player) { this.player = player; } @Override public int getHeight() { return 800; } @Override public int getWidth() { return 600; } @Override public void play() { for (int i = 0; i < 3; i++) { System.out.println("The video is loading,please wait..."); } System.out.println("Video loaded."); player.setState(player.getLoadedState()); player.play(); } } /** * 已加载状态 * * @author zangweiren 2010-4-8 * */ public class LoadedState implements MediaPlayerState { private MediaPlayerProxy player; public LoadedState(MediaPlayerProxy player) { this.player = player; } @Override public int getHeight() { return 1024; } @Override public int getWidth() { return 768; } @Override public void play() { for (int i = 0; i < 5; i++) { System.out.println("The video is playing...Height:" + player.getHeight() + ",Width:" + player.getWidth()); } System.out.println("Finished."); player.setState(player.getNotLoadedState()); } } /** * 视频播放器代理类 * * @author zangweiren 2010-4-8 * */ public class MediaPlayerProxy implements MediaPlayer { private MediaPlayerState notLoaded; private MediaPlayerState loading; private MediaPlayerState loaded; private MediaPlayerState state; public MediaPlayerProxy() { notLoaded = new NotLoadedState(this); loading = new LoadingState(this); loaded = new LoadedState(this); state = notLoaded; } @Override public int getHeight() { return state.getHeight(); } public MediaPlayerState getLoadedState() { return loaded; } public MediaPlayerState getLoadingState() { return loading; } public MediaPlayerState getNotLoadedState() { return notLoaded; } public MediaPlayerState getState() { return state; } @Override public int getWidth() { return state.getWidth(); } @Override public void play() { state.play(); } public void setState(MediaPlayerState state) { this.state = state; } } 测试程序: /** * 视频播放器测试程序 * * @author zangweiren 2010-4-8 * */ public class TestMediaPlayer { public static void main(String[] args) { MediaPlayer player = new MediaPlayerProxy(); System.out.println("Height:" + player.getHeight() + ",Width:" + player.getWidth()); player.play(); System.out.println("Height:" + player.getHeight() + ",Width:" + player.getWidth()); } }
测试结果:
引用
Height:800,Width:600
The video is loading,please wait...
The video is loading,please wait...
The video is loading,please wait...
Video loaded.
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
Finished.
Height:800,Width:600
The video is loading,please wait...
The video is loading,please wait...
The video is loading,please wait...
Video loaded.
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
Finished.
Height:800,Width:600
6、保护代理(Protect Proxy)模式实例
/** * 用户管理类接口 * * @author zangweiren 2010-4-8 * */ public interface UserManager { public abstract void addUser(String name); public abstract void deleteUser(String name); public abstract void updateUser(String name, HashMapproperties); } /** * 用户管理类 * * @author zangweiren 2010-4-8 * */ public class UserManagerImpl implements UserManager { @Override public void addUser(String name) { System.out.println("User:" + name + " has been added."); } @Override public void deleteUser(String name) { System.out.println("User:" + name + "has been deleted."); } @Override public void updateUser(String name, HashMap properties) { System.out.println("User:" + name + "has been updated."); System.out.println("Properties:"); Iterator keys = properties.keySet().iterator(); String key; while (keys.hasNext()) { key = keys.next(); System.out.println(key + "=" + properties.get(key)); } System.out.println("--------------"); } } /** * 管理员处理类 * * @author zangweiren 2010-4-8 * */ public class AdminInvocationHandler implements InvocationHandler { private UserManager manager; public AdminInvocationHandler(UserManager manager) { this.manager = manager; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { if (method.getName().equals("addUser")) { return method.invoke(manager, args); } else if (method.getName().equals("updateUser")) { return method.invoke(manager, args); } else if (method.getName().equals("deleteUser")) { return method.invoke(manager, args); } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } } /** * 普通用户处理类 * * @author zangweiren 2010-4-8 * */ public class UserInvocationHandler implements InvocationHandler { private UserManager manager; public UserInvocationHandler(UserManager manager) { this.manager = manager; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { if (method.getName().equals("addUser")) { throw new IllegalAccessException(); } else if (method.getName().equals("updateUser")) { return method.invoke(manager, args); } else if (method.getName().equals("deleteUser")) { throw new IllegalAccessException(); } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } } /** * 工具类 * * @author zangweiren 2010-4-8 * */ public class UserManagerUtils { public static UserManager getAdminProxy(UserManager manager) { return (UserManager) Proxy.newProxyInstance(manager.getClass() .getClassLoader(), manager.getClass().getInterfaces(), new AdminInvocationHandler(manager)); } public static UserManager getUserProxy(UserManager manager) { return (UserManager) Proxy.newProxyInstance(manager.getClass() .getClassLoader(), manager.getClass().getInterfaces(), new UserInvocationHandler(manager)); } } /** * 测试类 * * @author zangweiren 2010-4-8 * */ public class TestUserManager { public static void main(String[] args) { UserManager manager = new UserManagerImpl(); UserManager admin = UserManagerUtils.getAdminProxy(manager); admin.addUser("Jim"); HashMap properties = new HashMap (); properties.put("Gender", "male"); properties.put("Age", "28"); admin.updateUser("Jim", properties); admin.deleteUser("Jim"); System.out.println(); UserManager user = UserManagerUtils.getUserProxy(manager); try { user.addUser("Lily"); } catch (Exception e) { System.out.println("Can't add User!"); } properties = new HashMap (); properties.put("Gender", "female"); properties.put("Age", "26"); user.updateUser("Lily", properties); try { user.deleteUser("Lily"); } catch (Exception e) { System.out.println("Can't delete User!"); } } }
测试结果:
引用
User:Jim has been added.
User:Jimhas been updated.
Properties:
Age=28
Gender=male
--------------
User:Jimhas been deleted.
Can't add User!
User:Lilyhas been updated.
Properties:
Age=26
Gender=female
--------------
Can't delete User!
User:Jimhas been updated.
Properties:
Age=28
Gender=male
--------------
User:Jimhas been deleted.
Can't add User!
User:Lilyhas been updated.
Properties:
Age=26
Gender=female
--------------
Can't delete User!