java动态代理详解


在Java中,动态代理是一种强大的机制,允许开发者在运行时动态地创建接口的代理实例。这些代理实例在调用接口方法时,可以执行一些额外的操作,如日志记录、安全检查等,而无需修改接口的实现类。

### 动态代理的核心类

Java动态代理主要依赖于`java.lang.reflect`包中的两个类:`Proxy`和`InvocationHandler`。

- **`Proxy`**:提供了创建动态代理类和实例的静态方法。

- **`InvocationHandler`**:是一个接口,由代理实例的调用处理器实现,每个代理实例都有一个关联的调用处理器。

### 如何使用动态代理

1. **定义一个接口**:首先,你需要定义一个或多个接口,这些接口将被动态代理类实现。

2. **实现`InvocationHandler`接口**:创建一个实现了`InvocationHandler`接口的类,并实现`invoke`方法。在这个方法中,你可以添加自定义的逻辑,如日志记录、安全检查等。

3. **创建代理实例**:使用`Proxy`类的`newProxyInstance`静态方法创建代理实例。这个方法需要三个参数:类加载器、要实现的接口数组以及调用处理器实例。

### 示例代码

以下是一个简单的动态代理示例:


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("RealSubject: Handling request.");
    }
}

// 调用处理器
class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在方法调用之前可以添加自定义逻辑
        System.out.println("Before method: " + method.getName());

        // 调用原始对象的方法
        Object result = method.invoke(target, args);

        // 在方法调用之后可以添加自定义逻辑
        System.out.println("After method: " + method.getName());

        return result;
    }
}

public class DynamicProxyDemo {
    public static void main(String[] args) {
        // 创建原始对象
        RealSubject realSubject = new RealSubject();

        // 创建调用处理器
        MyInvocationHandler handler = new MyInvocationHandler(realSubject);

        // 创建代理对象
        Subject proxyInstance = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                new Class[]{Subject.class},
                handler
        );

        // 通过代理对象调用方法
        proxyInstance.request();
    }
}

在这个示例中,`RealSubject`类实现了`Subject`接口,并提供了`request`方法的实现。`MyInvocationHandler`类实现了`InvocationHandler`接口,并在`invoke`方法中添加了自定义的逻辑。最后,通过`Proxy.newProxyInstance`方法创建了`Subject`接口的代理实例,并通过这个代理实例调用了`request`方法。在调用`request`方法时,会先执行`MyInvocationHandler`中定义的自定义逻辑,然后调用原始对象的`request`方法,最后再次执行自定义逻辑。