在 Java 中,动态代理是一种设计模式,它允许你在运行时动态地创建对象的代理,而不需要在编译时知道实际对象的类。动态代理通常用于实现一些通用的功能,如日志记录、事务管理、安全性检查等,而不需要修改实际对象的代码。
动态代理的工作原理
-
定义接口:首先,你需要定义一个或多个接口,这些接口描述了代理对象需要实现的方法。
-
实现 InvocationHandler:
InvocationHandler
是一个接口,它是实现动态代理的关键。你需要创建一个InvocationHandler
的实现类,在其中定义代理对象的行为。 -
创建代理对象:使用
Proxy
类的newProxyInstance
方法创建代理对象。这个方法需要三个参数:ClassLoader
:用于定义代理类和实例化代理对象的类加载器。Class<?>[] interfaces
:代理对象需要实现的接口数组。InvocationHandler
:处理代理实例方法调用的调用处理器。
-
使用代理对象:创建的代理对象可以像使用实际对象一样使用,所有的方法调用都会被转发到
InvocationHandler
实现中。
示例代码
下面是一个简单的示例,展示如何使用 Java 的动态代理:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个接口
public interface Subject {
void performAction();
}
// 实现 InvocationHandler
public class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(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) {
// 创建实际对象
Subject realSubject = new Subject() {
@Override
public void performAction() {
System.out.println("Performing action in real subject.");
}
};
// 创建代理对象
Subject proxySubject = (Subject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
new ProxyHandler(realSubject)
);
// 使用代理对象
proxySubject.performAction();
}
}
在这个示例中,Subject
是一个接口,ProxyHandler
是 InvocationHandler
的实现,它在调用实际对象的方法前后添加了一些额外的行为。DynamicProxyDemo
类创建了一个实际的 Subject
对象和一个代理对象,然后通过代理对象调用 performAction
方法。
动态代理的优点
- 灵活性:可以在不修改实际对象代码的情况下,动态地添加功能。
- 解耦:将代理逻辑与实际对象逻辑分离,提高了代码的可维护性。
- 通用性:可以为不同的对象创建通用的代理逻辑。
动态代理是 Java 反射 API 的一个强大特性,它为实现 AOP(面向切面编程)提供了基础。