Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 6
Proxy.newProxyInstance() takes three arguments: the class loader that loaded the real subject, a list of interfaces implemented by the real subject,
and a reference to an invocation handler.
Every time you invoke a proxy's method, the proxy calls its invocation handler's invoke() method. The proxy passes itself to the invoke() method, along with a reference to the proxy's method and its list of arguments. In the preceding code, SimpleInvocationHandler.invoke() invokes the specified method on the real subject. Here's the output of the application listed in Example 5:
Before Calling doSomething Inside Method AClass.doSomething() After Calling doSomething
Example 6 shows how you can use the JDK's built-in support for the Proxy pattern to reimplement the image-icon proxy listed in Example 3:
import java.lang.reflect.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// This class tests a virtual proxy, which
// delays loading an expensive resource (an icon) until that
// resource is needed.
public class VirtualProxyTest extends JFrame {
private static String IMAGE_NAME = "mandrill.jpg";
private static final int IMAGE_WIDTH = 256, IMAGE_HEIGHT = 256,
SPACING = 5, FRAME_X = 150,
FRAME_Y = 200, FRAME_WIDTH = 530,
FRAME_HEIGHT = 286;
private ImageIcon imageIcon = null;
private Icon imageIconProxy = null;
static public void main(String args[]) {
VirtualProxyTest app = new VirtualProxyTest();
app.show();
}
public VirtualProxyTest() {
super("Virtual Proxy Test");
// Create an image icon and an image-icon proxy.
imageIcon = new ImageIcon(IMAGE_NAME);
imageIconProxy = (Icon)Proxy.newProxyInstance(
imageIcon.getClass().getClassLoader(),
imageIcon.getClass().getInterfaces(),
new ImageIconInvocationHandler(IMAGE_NAME,
IMAGE_WIDTH, IMAGE_HEIGHT));
// Set the bounds of the frame, and the frame's default
// close operation.
setBounds(FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
super.paint(g);
Insets insets = getInsets();
imageIcon.paintIcon(this, g, insets.left, insets.top);
imageIconProxy.paintIcon(this, g,
insets.left + IMAGE_WIDTH + SPACING, // width
insets.top); // height
}
}
// ImageIconInvocationHandler is a proxy for an icon.
// The proxy delays loading the image until the first time
// the image is drawn. While the icon is loading its image, the
// proxy draws a border and the message "Loading image..."
class ImageIconInvocationHandler implements InvocationHandler {
private static final String PAINT_ICON_METHOD="paintIcon",
GET_WIDTH_METHOD ="getIconWidth",
GET_HEIGHT_METHOD="getIconHeight";
private ImageIcon realIcon = null;
private boolean isIconCreated = false;
private String imageName = null;
private int width, height;
public ImageIconInvocationHandler(String imageName,
int width, int height) {
this.width = width;
this.height = height;
this.imageName = imageName;
}
public Object invoke(Object proxy, Method m, Object[] args) {
Object result = null;
if(PAINT_ICON_METHOD.equals(m.getName())) {
final Component c = (Component)args[0];
final Graphics g = (Graphics)args[1];
final int x = ((Integer)args[2]).intValue(),
y = ((Integer)args[3]).intValue();
if(isIconCreated) {
realIcon.paintIcon(c, g, x, y);
}
else {
g.drawRect(x, y, width-1, height-1);
g.drawString("Loading image...", x+20, y+20);
// The image is loaded via a Runnable passed to
// SwingUtilties.invokeLater(), which means that
// it is executed on another thread.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// Slow down the image-loading process.
Thread.currentThread().sleep(2000);
// ImageIcon constructor creates the image.
realIcon = new ImageIcon(imageName);
isIconCreated = true;
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
c.repaint();
}
});
}
}
else if(GET_WIDTH_METHOD.equals(m.getName())) {
return isIconCreated ? new Integer(height) :
new Integer(realIcon.getIconHeight());
}
else if(GET_HEIGHT_METHOD.equals(m.getName())) {
return isIconCreated ? new Integer(width) :
new Integer(realIcon.getIconWidth())rticle.txt
;
}
return null;
}
}
If you compare Example 6 with Example 3, you may conclude that the JDK's built-in support for the Proxy pattern is not for you, because Example 6 is a bit more complicated than Example 3. In this case, I would prefer Example 3 myself -- the JDK's built-in support for the Proxy pattern is much more useful when a proxy implements many methods that simply delegate to the real subject with only a few methods that embellish the real subject.