Java中的代理模式与动态代理

晨曦微光 2021-01-02 ⋅ 15 阅读

什么是代理模式?

代理模式是一种设计模式,它允许一个对象(代理对象)可以代表另一个对象(真实对象)进行一些操作,从而控制对真实对象的访问。通过使用代理,我们可以在不改变原始对象的情况下,增加一些额外的逻辑。

静态代理

在静态代理中,代理类和真实类实现了相同的接口,代理类持有一个真实类的引用,并在必要的时候委托真实类的方法。静态代理的缺点在于每个需要代理的类都需要单独创建一个代理类。

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包下的ProxyInvocationHandler接口来实现动态代理。

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()方法,我们可以动态地创建一个代理对象。

动态代理的应用场景

  1. AOP(面向切面编程):通过动态代理可以在不修改原代码的情况下,动态地为方法添加额外的逻辑。
  2. 远程方法调用(RMI):通过动态代理可以隐藏底层的网络通信细节,让调用远程方法就像调用本地方法一样简单。

总结:代理模式和动态代理模式都是一种非常有用的设计模式,通过它们可以实现代码的解耦合、添加额外的逻辑和隐藏底层细节。在Java中,可以使用静态代理来实现简单的逻辑增强,而动态代理则可以在运行时动态生成代理类,更加灵活和可扩展。


全部评论: 0

    我有话说: