Java代理模式详细
一、引言
代理模式(Proxy Pattern)是一种常用的设计模式,它为其他对象提供一种代理以控制对这个对象的访问。在Java中,代理模式可以分为静态代理和动态代理两种。本文将详细介绍代理模式的概念、实现方式以及应用场景。
二、代理模式的概念
代理模式是一种对象结构型模式,它给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理模式涉及三个角色:
- 抽象角色(Subject):声明了真实对象和代理对象的共同接口。
- 真实角色(RealSubject):代理对象所代表的真实对象,是最终要引用的对象。
- 代理角色(Proxy):代理对象,内部含有对真实对象的引用,并且可以控制对真实对象的访问,同时可以在客户端和目标对象之间起到中介的作用。
三、静态代理
静态代理是指在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
实现步骤
- 创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。
- 创建一个代理类,同时使其也实现这个接口。
- 在代理类中持有一个被代理对象的引用,并在代理类中的方法中调用该对象的方法。
示例代码
// 接口
public interface Subject {void request();
}// 真实角色
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("执行真实对象的方法!");}
}// 代理角色
public class ProxySubject implements Subject {private RealSubject realSubject;@Overridepublic void request() {if (realSubject == null) {realSubject = new RealSubject();}preRequest();realSubject.request(); // 调用真实对象的方法postRequest();}// 在请求之前执行private void preRequest() {System.out.println("调用真实对象之前的服务。");}// 在请求之后执行private void postRequest() {System.out.println("调用真实对象之后的服务。");}
}// 客户端
public class Client {public static void main(String[] args) {Subject subject = new ProxySubject();subject.request(); // 客户端通过代理对象访问真实对象的方法}
}
四、动态代理
动态代理是指在程序运行时动态地创建代理对象,并实现对真实对象的代理访问。Java中的动态代理主要依赖于java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口。
实现步骤
- 创建一个实现接口
InvocationHandler
的类,它必须实现invoke
方法,以供代理实例的调用处理程序使用。 - 创建被代理的类以及接口。
- 通过
Proxy
的newProxyInstance
静态方法创建代理对象,该方法需要接收三个参数:类加载器、一组接口以及调用处理器实例。
示例代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 真实角色
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("执行真实对象的方法!");}
}// 调用处理器
public class DynamicProxy implements InvocationHandler {private Object subject;public DynamicProxy(Object subject) {this.subject = subject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {preRequest();Object result = method.invoke(subject, args);postRequest();return result;}private void preRequest() {System.out.println("调用真实对象之前的服务。");}private void postRequest() {System.out.println("调用真实对象之后的服务。");}
}// 客户端
public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new DynamicProxy(realSubject));proxy.request(); // 客户端通过代理对象访问真实对象的方法}
}
五、代理模式的应用场景
- 远程代理:为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。
- 虚拟代理:根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。
- 保护代理:控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
- 智能指引:取代了简单的指针,它在访问对象时执行一些附加操作,比如:对指向实际对象的引用计数、第一次引用一个持久对象时,将它装入内存等。
六、总结
代理模式是一种非常有用的设计模式,它可以在不修改原始类代码的情况下,通过引入代理类来给原始类附加额外的功能或控制。在Java中,静态代理和动态代理是实现代理模式的两种主要方式,它们各自适用于不同的场景。理解并掌握代理模式对于提高代码的可维护性和可扩展性具有重要意义。