在编程中,代理模式(Proxy Pattern)是一种设计模式,用于在不修改原始对象的情况下控制对其的访问。代理可以分为静态代理和动态代理,它们在实现方式和应用场景上有所不同。
静态代理
定义:静态代理是在编译时创建代理类。代理类和被代理类都需要在编译时就确定下来,代理类实现了与被代理类相同的接口,并在其方法中调用被代理对象的方法。这种代理模式的代理类是固定的,不能在运行时改变。
特点:
- 代理类是在编译时生成的。
- 代理类和被代理类在编译时是已知的。
- 代理类需要显式地实现被代理类的接口。
示例:
假设有一个接口 Subject
和一个实现类 RealSubject
,现在需要创建一个代理类 ProxySubject
来控制对 RealSubject
的访问。
java
// 接口
public interface Subject {
void request();
}
// 真实对象
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 代理对象
public class ProxySubject implements Subject {
private RealSubject realSubject;
public ProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
System.out.println("ProxySubject: Before real request.");
realSubject.request();
System.out.println("ProxySubject: After real request.");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
ProxySubject proxySubject = new ProxySubject(realSubject);
proxySubject.request();
}
}
输出:
ProxySubject: Before real request.
RealSubject: Handling request.
ProxySubject: After real request.
在这个示例中,ProxySubject
是静态代理,它在编译时就知道需要代理哪个 RealSubject
对象。
动态代理
定义 :动态代理是在运行时创建代理类。动态代理允许你在运行时生成代理对象,而不需要在编译时就确定代理类。Java 提供了 java.lang.reflect.Proxy
类和 InvocationHandler
接口来实现动态代理。
特点:
- 代理类是在运行时生成的。
- 代理类和被代理类在运行时动态绑定。
- 不需要显式地创建代理类,只需定义一个
InvocationHandler
实现即可。
示例:
使用 Java 的动态代理来实现上述的代理功能:
java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 接口
public interface Subject {
void request();
}
// 真实对象
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 动态代理处理器
public class DynamicProxyHandler implements InvocationHandler {
private Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxy: Before real request.");
Object result = method.invoke(target, args);
System.out.println("Proxy: After real request.");
return result;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Subject proxyInstance = (Subject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
new DynamicProxyHandler(realSubject)
);
proxyInstance.request();
}
}
输出:
Proxy: Before real request.
RealSubject: Handling request.
Proxy: After real request.
在这个示例中,Proxy.newProxyInstance
方法创建了一个动态代理实例,它在运行时动态处理对 RealSubject
的方法调用。
区别总结
-
生成方式:
- 静态代理:代理类在编译时已存在,并且需要在编写代码时显式定义。
- 动态代理:代理类在运行时生成,可以在运行时灵活地创建和修改。
-
灵活性:
- 静态代理:代理类的逻辑是固定的,修改代理行为需要修改代码并重新编译。
- 动态代理 :可以通过
InvocationHandler
灵活地处理方法调用,无需修改现有代码。
-
使用场景:
- 静态代理:适用于代理逻辑较为固定,且代理类不需要在运行时变化的情况。
- 动态代理:适用于代理逻辑动态变化或需要为多个类生成代理的场景,特别是在框架中经常使用。
这两种代理方式各有优缺点,根据具体需求选择适合的代理方式。