请解释Java中的代理模式,分别介绍静态代理和动态代理
代理模式是一种常见的设计模式,它允许一个对象(代理对象)代表另一个对象(被代理对象)进行访问控制,以控制对对象的访问。代理模式可以在不改变原始对象的情况下,增加额外的功能或控制访问。
- 静态代理:
静态代理是在编译时确定代理关系,即代理类和被代理类的关系在编译时已经确定,代理类是直接实现了与被代理类相同的接口或者继承了与被代理类相同的父类。
特点:
静态代理在编译时确定代理关系,因此代理类的代码是固定的,不会在运行时改变。
代理类需要显式地调用被代理对象的方法,在代理对象的方法中可以添加额外的逻辑。
示例:
java
// 定义接口
interface Subject {
void request();
}
// 实现被代理类
class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 实现代理类
class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
public void request() {
System.out.println("Proxy: Handling request.");
realSubject.request(); // 调用被代理对象的方法
}
}
// 使用静态代理
public class StaticProxyDemo {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.request();
}
}
- 动态代理:
动态代理是在运行时生成代理类,代理类不是在编译时确定的,而是根据被代理的接口或者父类在运行时动态生成的。
特点:
动态代理不需要显式地实现被代理类的接口或者继承被代理类的父类,而是通过 Java 提供的代理类和反射机制来动态生成代理类。
动态代理可以在运行时根据需要代理不同的对象,因此更加灵活。
示例:
java
import java.lang.reflect.*;
// 定义接口
interface Subject {
void request();
}
// 实现被代理类
class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 使用动态代理
public class DynamicProxyDemo {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxy = (Subject) Proxy.newProxyInstance(
Subject.class.getClassLoader(),
new Class[] { Subject.class },
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Dynamic Proxy: Handling request.");
return method.invoke(realSubject, args);
}
}
);
proxy.request();
}
}
- 区别和应用场景:
静态代理:在编译时就已经确定了代理关系,代理类和被代理类之间的关系是固定的。适用于代理类数量较少、代理逻辑不变的情况。
动态代理:在运行时动态生成代理类,代理类的生成过程由程序自动生成,更加灵活。适用于代理类数量较多、代理逻辑可能变化的情况。
总的来说,静态代理和动态代理都是代理模式的实现方式,它们在不同的场景下有不同的应用。