Java Proxy Pattern Implementation Guide
There are two common ways to implement the proxy pattern in Java: static proxy and dynamic proxy.
- Static proxy:
Static proxy refers to the relationship between the proxy class and the target class being determined at compile time. Both the proxy class and the target class implement the same interface. The proxy class holds an object of the target class, calls the methods of the target class within the proxy class, and adds additional logic before and after the method calls. Here is a simple example of static proxy:
// 接口
interface Image {
void display();
}
// 被代理类
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image from disk: " + fileName);
}
public void display() {
System.out.println("Displaying image: " + fileName);
}
}
// 代理类
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
image.display();
}
}
- An object of type java.lang.reflect.Proxy.
- A class called InvocationHandler in the java.lang.reflect package.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 接口
interface Image {
void display();
}
// 被代理类
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image from disk: " + fileName);
}
public void display() {
System.out.println("Displaying image: " + fileName);
}
}
// InvocationHandler实现
class ImageInvocationHandler implements InvocationHandler {
private Image image;
public ImageInvocationHandler(Image image) {
this.image = image;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method " + method.getName());
Object result = method.invoke(image, args);
System.out.println("After method " + method.getName());
return result;
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Image realImage = new RealImage("test.jpg");
Image dynamicProxy = (Image) Proxy.newProxyInstance(
realImage.getClass().getClassLoader(),
realImage.getClass().getInterfaces(),
new ImageInvocationHandler(realImage));
dynamicProxy.display();
}
}
Whether it’s static proxy or dynamic proxy, the proxy class can add extra logic before and after the methods of the class being proxied, thus achieving control and enhancement of the class being proxied. The advantage of dynamic proxy over static proxy is that it simplifies the writing of proxy classes and allows one proxy class to proxy multiple interfaces.