什么是代理模式?
代理模式是一种设计模式,它允许一个对象(代理对象)可以代表另一个对象(真实对象)进行一些操作,从而控制对真实对象的访问。通过使用代理,我们可以在不改变原始对象的情况下,增加一些额外的逻辑。
静态代理
在静态代理中,代理类和真实类实现了相同的接口,代理类持有一个真实类的引用,并在必要的时候委托真实类的方法。静态代理的缺点在于每个需要代理的类都需要单独创建一个代理类。
public interface Image {
void display();
}
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
public class ProxyImage implements Image {
private RealImage realImage;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
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("image.jpg");
image.display();
}
}
动态代理
Java中的动态代理机制允许在运行时动态生成代理类和代理实例。使用动态代理,我们可以仅编写一个代理类,它可以代理多个真实类,从而减少了重复编码的工作量。
在Java中,使用java.lang.reflect
包下的Proxy
和InvocationHandler
接口来实现动态代理。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public interface Image {
void display();
}
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
public class ImageProxyHandler implements InvocationHandler {
private Object realObject;
public ImageProxyHandler(Object realObject) {
this.realObject = realObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
if (method.getName().equals("display")) {
System.out.println("Before displaying image");
result = method.invoke(realObject, args);
System.out.println("After displaying image");
} else {
result = method.invoke(realObject, args);
}
return result;
}
}
public class Main {
public static void main(String[] args) {
Image realImage = new RealImage("image.jpg");
InvocationHandler handler = new ImageProxyHandler(realImage);
Image proxyImage = (Image) Proxy.newProxyInstance(
Image.class.getClassLoader(),
new Class[]{Image.class},
handler
);
proxyImage.display();
}
}
在上面的例子中,ImageProxyHandler
实现了InvocationHandler
接口,所有对代理对象的方法调用都会被重定向到invoke
方法中,在该方法中我们可以进行额外的操作。通过Proxy.newProxyInstance()
方法,我们可以动态地创建一个代理对象。
动态代理的应用场景
- AOP(面向切面编程):通过动态代理可以在不修改原代码的情况下,动态地为方法添加额外的逻辑。
- 远程方法调用(RMI):通过动态代理可以隐藏底层的网络通信细节,让调用远程方法就像调用本地方法一样简单。
总结:代理模式和动态代理模式都是一种非常有用的设计模式,通过它们可以实现代码的解耦合、添加额外的逻辑和隐藏底层细节。在Java中,可以使用静态代理来实现简单的逻辑增强,而动态代理则可以在运行时动态生成代理类,更加灵活和可扩展。
本文来自极简博客,作者:晨曦微光,转载请注明原文链接:Java中的代理模式与动态代理