文章目录
- 1.概念
- 1.1 什么是代理模式
- 1.2 优点与缺点
- 2.实现方式
- 2.1 静态代理
- 2.2 动态代理
- 3. Java 哪些地方用到了代理模式
- 4. Spring 哪些地方用到了代理模式
1.概念
1.1 什么是代理模式
代理模式
(Proxy Pattern)是一种结构型设计模式,它允许通过一个代理对象来控制对另一个对象的访问。
1.2 优点与缺点
优点:
1.可以控制对真实对象的访问。
2.可以延迟真实对象的创建,减少系统开销。
3.可以提供额外的服务,如缓存、权限检查等。
缺点:
1.增加了系统的复杂性,因为引入了额外的代理类。
2.可能会降低系统的性能,因为代理会增加一层间接调用。
2.实现方式
2.1 静态代理
// Image接口
public interface Image {void display();
}// RealImage类,实现了Image接口
public class RealImage implements Image {private String fileName;// 构造函数,加载图像public RealImage(String fileName) {this.fileName = fileName;loadImageFromDisk();}// 加载图像的模拟方法private void loadImageFromDisk() {System.out.println("Loading " + fileName);}// 显示图像@Overridepublic void display() {System.out.println("Displaying " + fileName);}
}// Image代理类
public class ImageProxy implements Image {private String fileName;private Image realImage;// 构造函数public ImageProxy(String fileName) {this.fileName = fileName;}// 显示图像,如果真实图像尚未加载,则先加载@Overridepublic void display() {if (realImage == null) {realImage = new RealImage(fileName);}realImage.display();}
}// 测试类
public class ProxyPatternDemo {public static void main(String[] args) {Image image = new ImageProxy("test_10mb.jpg");// 图像将从磁盘加载image.display();System.out.println("");// 图像不需要从磁盘加载image.display();}
}
2.2 动态代理
动态代理通常使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。
// Image接口
public interface Image {void display();
}// RealImage类,实现了Image接口
public class RealImage implements Image {private String fileName;// 构造函数,加载图像public RealImage(String fileName) {this.fileName = fileName;loadImageFromDisk();}// 加载图像的模拟方法private void loadImageFromDisk() {System.out.println("Loading " + fileName);}// 显示图像@Overridepublic void display() {System.out.println("Displaying " + fileName);}
}// 动态代理类
public class DynamicImageProxy {public static Image newInstance(String fileName) {return (Image) java.lang.reflect.Proxy.newProxyInstance(Image.class.getClassLoader(),new Class[]{Image.class},new java.lang.reflect.InvocationHandler() {private Image realImage = null;@Overridepublic Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {if (realImage == null) {realImage = new RealImage(fileName);}return method.invoke(realImage, args);}});}
}// 测试类
public class ProxyPatternDemo {public static void main(String[] args) {Image image = DynamicImageProxy.newInstance("test_10mb.jpg");// 图像将从磁盘加载image.display();System.out.println("");// 图像不需要从磁盘加载image.display();}
}
3. Java 哪些地方用到了代理模式
RMI
(Remote Method Invocation): Java的RMI机制使用代理模式来实现远程对象的透明访问。RMI系统提供的代理类将远程方法调用转换为对远程对象的调用。
JDBC
(Java Database Connectivity): JDBC驱动程序管理器使用代理模式来加载和实例化JDBC驱动程序。当应用程序请求连接到数据库时,代理会加载适当的驱动程序并建立连接。
动态代理
: Java的动态代理机制允许在运行时创建代理类和代理实例。这通常用于AOP(面向切面编程)框架,如Spring AOP,其中代理用于在目标对象的方法调用前后执行增强代码。
事件监听器
: 在Swing或其他GUI框架中,事件监听器使用代理模式来处理事件。事件源将事件委托给事件监听器,后者作为事件处理的代理。
延迟加载
: 在Hibernate或其他ORM框架中,代理模式用于实现延迟加载。代理对象代表真实对象,并在真正需要访问对象数据时才加载数据。
保护代理
: 在需要控制对资源的访问时,可以使用保护代理来检查调用者的权限,并根据权限决定是否允许访问资源。
智能引用
: 在需要跟踪对象的使用情况时,可以使用智能代理来记录对象的使用次数、最后使用时间等信息。
4. Spring 哪些地方用到了代理模式
AOP
(面向切面编程): Spring AOP使用代理模式来实现方法拦截。Spring的AopProxy类充当代理,它根据配置创建代理对象,并在目标对象的方法调用前后执行增强代码。
事务管理
: Spring的事务管理器使用代理模式来管理事务。TransactionInterceptor类充当代理,它在目标方法执行前后管理事务的开启、提交或回滚。
事件发布
: Spring的事件驱动模型使用代理模式来解耦事件的生产者和消费者。ApplicationEventMulticaster类充当代理,它将事件发布给所有注册的监听器。
Web集成
: Spring的Web模块使用代理模式来集成不同的Web框架。例如,DispatcherServlet充当代理,它将HTTP请求转换为Spring MVC框架的调用。
资源访问
: Spring的ResourceLoader和Resource接口使用代理模式来抽象不同类型的资源访问。ResourceLoader的实现类充当代理,它们将资源访问的调用转换为具体文件系统、类路径或URL的访问。
消息服务
: Spring的JMS(Java消息服务)集成使用代理模式来适配不同的消息中间件。JmsTemplate和JmsListenerContainerFactory类充当代理,它们将Spring的消息抽象转换为具体的消息中间件操作。