在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`方法,最后再次执行自定义逻辑。