java 静态代理 动态代理深入学习


在Java中,代理模式是一种常用的设计模式,用于为其他对象提供一种代理以控制对这个对象的访问。代理模式主要分为静态代理和动态代理两种。

### 静态代理

静态代理是在程序编译时期就已经确定的代理类。代理类与被代理类实现同一个接口(或被代理类继承自同一个父类),在代理类中通过调用被代理类的方法来执行具体的操作,同时可以在调用前后添加自定义的逻辑。

**示例代码**(假设有一个接口`Subject`和两个实现类`RealSubject`、`StaticProxy`):


interface Subject {
    void request();
}

class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("Executing real request.");
    }
}

class StaticProxy implements Subject {
    private Subject realSubject;

    public StaticProxy(Subject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        preRequest();
        realSubject.request();
        postRequest();
    }

    private void preRequest() {
        System.out.println("Before real request.");
    }

    private void postRequest() {
        System.out.println("After real request.");
    }
}

// 使用
public class ProxyPatternDemo {
    public static void main(String[] args) {
        Subject realSubject = new RealSubject();
        Subject proxy = new StaticProxy(realSubject);
        proxy.request();
    }
}

### 动态代理

动态代理是在程序运行时动态生成的代理类。它主要利用了Java的反射(Reflection)机制,在运行时动态地创建代理类的字节码,并加载到JVM中。Java的动态代理通常是通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现的。

**示例代码**(使用JDK动态代理):


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Subject {
    void request();
}

class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("Executing real request.");
    }
}

class DynamicProxyHandler implements InvocationHandler {
    private Object subject;

    public DynamicProxyHandler(Object subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        preRequest();
        Object result = method.invoke(subject, args);
        postRequest();
        return result;
    }

    private void preRequest() {
        System.out.println("Before real request.");
    }

    private void postRequest() {
        System.out.println("After real request.");
    }

    @SuppressWarnings("unchecked")
    public static <T> T getProxyInstance(T subject) {
        return (T) Proxy.newProxyInstance(
            subject.getClass().getClassLoader(),
            subject.getClass().getInterfaces(),
            new DynamicProxyHandler(subject)
        );
    }
}

// 使用
public class ProxyPatternDemo {
    public static void main(String[] args) {
        Subject realSubject = new RealSubject();
        Subject proxy = DynamicProxyHandler.getProxyInstance(realSubject);
        proxy.request();
    }
}

在上面的动态代理示例中,`DynamicProxyHandler`类实现了`InvocationHandler`接口,并通过`Proxy.newProxyInstance`方法创建了代理类的实例。这个代理类在运行时动态生成,并且实现了与`RealSubject`相同的接口`Subject`。当调用代理类的`request`方法时,实际上会调用`DynamicProxyHandler`的`invoke`方法,从而实现了在调用前后添加自定义逻辑的功能。