RMI:
1. Create a remote interface, which provides a set of methods that can be called remotely.
2. Make sure all arguments and return type in the interface are serializable.
3. You can declare transient variable so it will not be serialized.
Proxy Pattern: provides a surrogate or placeholder for another object to control access to it.
Use the proxy pattern to create a representation object that control access to another object, which may be remote, expensive to create or in need of securing.
A remote proxy controls access to a remote object.
A virtual proxy controls access to a resource that is expensive to create.
A protection proxy controls access to a resource based on access rights.
Virtual Proxy:
The virtual proxy often defers the creation of the object until it is needed; the Virtual Proxy also acts as a surrogate for the object before and while it is being created. After that, the proxy delegates requests directly to the Real Object.
虚拟代理:在对象创建时添加行为。Proxy里含有这个对象,当调用Proxy时,这个对象才被创建。
定义代理:
public class ImageProxy implements Icon {
ImageIcon imageIcon;
URL imageURL;
Thread retrieveThread;
boolean retrieving = false;
public ImageProxy(URL url) {
imageURL = url;
}
@Override
public int getIconHeight() {
if (imageIcon != null) {
return imageIcon.getIconHeight();
} else {
return 600;
}
}
@Override
public int getIconWidth() {
if (imageIcon != null) {
return imageIcon.getIconWidth();
} else {
return 600;
}
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
if (imageIcon != null) {
imageIcon.paintIcon(c, g, x, y);
} else {
g.drawString("Downloading image...", x + 300, y + 300);
if (!retrieving) {
retrieving = true;
retrieveThread = new Thread(new Runnable() {
@Override
public void run() {
imageIcon = new ImageIcon(imageURL, "image");
c.repaint();
}
});
retrieveThread.start();
}
}
}
}
定义Client:
public class ImageProxyTestDrive {
JFrame frame = new JFrame("Image Proxy");
ImageComponent image;
JMenuBar menuBar;
JMenu menu;
Hashtable<String, URL> images = new Hashtable<String, URL>();
public static void main(String[] args) throws Exception {
ImageProxyTestDrive test = new ImageProxyTestDrive();
}
public ImageProxyTestDrive() throws Exception {
images.put(
"Image1",
new URL(
"http://stuffpoint.com/nature/image/24701-nature-natural-beauty.jpg"));
images.put(
"Images2",
new URL(
"http://stuffpoint.com/nature/image/43316-nature-gorgeous-waterfall-wallpaper.jpg"));
images.put("Images3", new URL(
"http://stuffpoint.com/nature/image/58924-nature-paradise.jpg"));
Icon icon = new ImageProxy(images.get("Image1"));
image = new ImageComponent(icon);
menu = new JMenu("Menu");
for (Enumeration<String> e = images.keys(); e.hasMoreElements();) {
JMenuItem menuItem = new JMenuItem(e.nextElement());
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
image.setIcon(new ImageProxy(images.get(e
.getActionCommand())));
frame.repaint();
}
});
menu.add(menuItem);
}
menuBar = new JMenuBar();
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.getContentPane().add(image);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
}
}
class ImageComponent extends JComponent {
private static final long serialVersionUID = 2034018324585301738L;
private Icon icon;
public ImageComponent(Icon icon) {
this.icon = icon;
}
public void setIcon(Icon icon) {
this.icon = icon;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = icon.getIconWidth();
int h = icon.getIconHeight();
int x = (800 - w) / 2;
int y = (600 - h) / 2;
icon.paintIcon(this, g, x, y);
}
}
上例中当菜单项被点击后,下载图片并显示。图片加载前显示文字,另开线程下载,下载完成后显示图片。
应用:load图片(先显示loading...,加载完再显示图片)。
In java.lang.reflect package, Java lets you creates a proxy class on the fly that implements one or more interfaces and forwards method invocations to a class that you specify. Because the actual proxy class is created at runtime, we refer to this Java technology as a dynamic proxy.
Protection Proxy consists two classes: Proxy and InvocationHandler.
InvocationHandler gets passed all method calls that are invoked on the Proxy, which controls access to the methods of the Real Object. The job of InvocationHandler is to respond to any method calls on the Proxy.
保护代理用来控制对象方法的访问权限。调用对象方法时,不是直接引用对象访问,而是在其代理上调用,由代理控制访问权限。保护代理有两部分组成,一是代理,二是调用处理。代理由java自动生成,在代理上调用方法时,会根据调用处理里的代码执行。
定义Real Object:
public interface PersonBean {
String getName();
String getGender();
String getInterests();
int getHotOrNotRating();
void setName(String name);
void setGender(String gender);
void setInterests(String interests);
void setHotOrNotRating(int rating);
}
public class PersonBeanImpl implements PersonBean {
String name;
String gender;
String interests;
int rating;
int ratingCount = 0;
@Override
public String getName() {
return name;
}
@Override
public String getGender() {
return gender;
}
@Override
public String getInterests() {
return interests;
}
@Override
public int getHotOrNotRating() {
return (ratingCount == 0 ? 0 : rating / ratingCount);
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public void setGender(String gender) {
this.gender = gender;
}
@Override
public void setInterests(String interests) {
this.interests = interests;
}
@Override
public void setHotOrNotRating(int rating) {
this.rating += rating;
ratingCount++;
}
}
定义Invocation Handler:
import java.lang.reflect.*;
public class OwnerInvocationHandler implements InvocationHandler {
PersonBean person;
public OwnerInvocationHandler(PersonBean person) {
this.person = person;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if(method.getName().equals("setHotOrNotRating")) {
throw new IllegalAccessException();
} else if(method.getName().startsWith("set")) {
return method.invoke(person, args);
}
return null;
}
}
import java.lang.reflect.*;
public class NonOwnerInvocationHandler implements InvocationHandler {
PersonBean person;
public NonOwnerInvocationHandler(PersonBean person) {
this.person = person;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
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();
}
return null;
}
}
定义Client:
import java.lang.reflect.Proxy;
public class MatchMakingTestDrive {
public static void main(String[] args) {
MatchMakingTestDrive test = new MatchMakingTestDrive();
test.drive();
}
public void drive() {
PersonBean joe = new PersonBeanImpl();
joe.setName("Joe");
joe.setGender("male");
PersonBean ownerProxy = getOwnerProxy(joe);
System.out.println("Name is " + ownerProxy.getName());
ownerProxy.setInterests("Badminton");
System.out.println("Interest set to " + ownerProxy.getInterests());
try {
ownerProxy.setHotOrNotRating(10);
} catch (Exception e) {
System.out.println("Can't set rating from owner proxy");
}
System.out.println("Rating is " + ownerProxy.getHotOrNotRating());
}
PersonBean getOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(person.getClass()
.getClassLoader(), person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}
PersonBean getNonOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(person.getClass()
.getClassLoader(), person.getClass().getInterfaces(),
new NonOwnerInvocationHandler(person));
}
}
在上面例子中,一个PersonBean对象有两个Proxy,一个是以PersonBean的拥有者身份使用的Proxy,一个是以PersonBean的非拥有者身份使用的Proxy。两个Proxy对PersonBean中方法的访问权限不同。当越权访问时,会产生异常。
应用:用户访问权限
Proxy Variants:
Firewall Proxy: controls access to a set of network resources, protecting the subject from "bad" clients.
Smart Reference Proxy: provides additional actions whenever a subject is referenced, such as counting the number of references to an object.
Caching Proxy: provides temporary storage for results of operations that are expensive. It can also allow multiple clients to share the results to reduce computation or network latency.
Synchronization Proxy: provides safe access to a subject from multiple threads.
Complexity Hiding Proxy: hides the complexity of and controls access to a complex set of classes. This is sometimes called Facade Proxy. Facade Pattern provides an alternative interface, but Facade Proxy controls access.
Copy-On-Write Proxy: controls the copying of an object by deferring the copying of an object until it is required by a client. This is a variant of the Virtual Proxy.