Java 动态代理运用了设计模式中常用的代理模式。以下是关于代理模式及相关概念的详细解释:
代理模式: 目的就是为其他对象提供一个代理用来控制对某个真实对象的访问。
代理的基本构成:
Subject 角色:定义了真实角色和代理角色需要实现的方法。
RealSubject 角色:真正实现业务服务的对象。
Proxy 角色:负责将自身的 Request 请求,调用 RealSubject 对应的 request 功能实现业务功能,自身不做真正的业务处理。
静态代理模式与动态代理模式的区别:
1. 静态代理模式: 在代码阶段规定这种代理关系。Proxy 类通过编译器编译成 class 文件。在系统运行时,此 class 已经存在。静态代理可以访问无法直接访问的资源,增强现有的接口业务功能。大量地使用静态代理会使系统内的类规模增大,并且不易维护。因为 Proxy 和 RealSubject 的功能本质上是相同的,Proxy 只是作为中介。
2. 动态代理模式: 在运行状态中,根据 Subject 和 RealSubject,动态地创建一个 Proxy。Proxy 使用完后,就会销毁,这样就可以避免 Proxy 角色的 class 在系统中的冗余问题。
在 Java 中,`java.lang.reflect.Proxy` 类是动态代理机制的主类,它提供一组静态方法为一组接口动态的生成对象和代理类。`InvocationHandler` 是调用处理器接口,自定义的 `invoke` 方法用于实现对真正委托类的代理访问。
Java 动态代理工作机制:
1. 确定接口对类装载器是否可见,并确保是 interface 类型而不是 class 类型。
2. 从 loaderToCache 映射表中获取以类装载器对象为关键字所对应的缓存表。如果不存在,就会创建一个新的缓存表并更新到 loaderToCache 中。
3. 根据接口的 public 情况,动态创建代理类的 class 对象。名称格式为 `$ProxyN`。
4. 代码生成过程结束后,根据结果更新缓存表。如果代理类成功生成则更新缓存表中的类对象引用,否则清除对应的关键值,并唤醒所有可能的正在等待的线程。
Java 动态代理实例:
可以通过定义接口、实现这些接口的 RealSubject 类、以及实现 `InvocationHandler` 接口的自定义处理器来创建 ElectricCar 的动态代理类。然后使用 `Proxy.newProxyInstance()` 方法来生成动态代理对象。这个方法需要三个参数:类装载器、接口列表和 `InvocationHandler` 实例。