在 Java 开发中,代理模式是一种非常重要的设计模式,广泛应用于 AOP(面向切面编程)、动态代理等领域。本文将结合代码示例和思维导图,深入解析 Java 中的代理模式,包括静态代理和动态代理的实现方式及其应用场景。
1. 什么是代理
代理模式的核心思想是:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。代理对象可以在不修改目标对象的情况下,对目标对象的功能进行增强或控制访问。
2. 代理的目的
代理模式的主要目的是:
-
控制访问:通过代理对象的方式间接访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性。
-
功能增强:通过代理对象对原有业务进行增强,例如添加日志、事务管理、权限校验等功能。
3. 如何实现代理
在 Java 中,代理的实现方式主要有两种:
-
静态代理:由程序员手动编写代理类,代理类在编译时就已经确定。
-
动态代理:代理类在运行时动态生成,常用的实现方式有 JDK 动态代理和 CGLIB 动态代理。
4. 静态代理
4.1 静态代理的结构
静态代理的核心结构如下:
-
目标类:实现业务逻辑的类。
-
代理类:实现与目标类相同的接口,并在代理方法中调用目标类的方法,同时可以添加额外的功能。
4.2 静态代理的代码示例
4.2.1 目标类
package com.qcby;
public class ClothesFactory implements ByClothes {
@Override
public void clothes(String size) {
System.out.println("已经给您定制好了一件大小为 " + size + " 的衣服");
}
public void 机器处理() {
System.out.println("机器正在处理衣服");
}
public void 原材料() {
System.out.println("准备原材料");
}
}
4.2.2 代理类
package com.qcby;
public class Proxy implements ByClothes {
private ClothesFactory clothesFactory = new ClothesFactory();
@Override
public void clothes(String size) {
FrontService();
clothesFactory.clothes(size);
endService();
}
// 前置服务
public void FrontService() {
System.out.println("根据您的需求进行市场调研");
}
// 后置服务
public void endService() {
System.out.println("为您提供一条龙的包办服务");
}
}
4.2.3 测试类
package com.qcby;
public class Test {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.clothes("XXXL");
}
}
4.2.4 输出结果
根据您的需求进行市场调研
已经给您定制好了一件大小为 XXXL 的衣服
为您提供一条龙的包办服务
4.3 静态代理的优缺点
优点:
-
实现简单,易于理解。
-
代理类可以对目标类的功能进行灵活的增强。
缺点:
-
每增加一个目标类,就需要增加一个对应的代理类,代码量较大。
-
如果目标类的方法较多,代理类的代码也会变得冗长。
5. 动态代理
5.1 动态代理的原理
动态代理的核心是利用 Java 的反射机制,在运行时动态生成代理类。动态代理类实现了与目标类相同的接口,并通过 InvocationHandler
接口来拦截方法调用。
5.2 JDK 动态代理的代码示例
5.2.1 目标类
package com.qcby;
public class ClothesFactory implements ByClothes {
@Override
public void clothes(String size) {
System.out.println("已经给您定制好了一件大小为 " + size + " 的衣服");
}
}
5.2.2 代理工厂类
package com.qcby;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DyProxy implements InvocationHandler {
private Object target;
public DyProxy(Object target) {
this.target = target;
}
public Object getProxyInterFace() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
FrontService();
Object result = method.invoke(target, args);
endService();
return result;
}
// 前置服务
private void FrontService() {
System.out.println("根据您的需求进行市场调研");
}
// 后置服务
private void endService() {
System.out.println("为您提供一条龙的包办服务");
}
}
5.2.3 测试类
package com.qcby;
public class Test {
public static void main(String[] args) {
ClothesFactory clothesFactory = new ClothesFactory();
ByClothes proxy = (ByClothes) new DyProxy(clothesFactory).getProxyInterFace();
proxy.clothes("XXXL");
}
}
5.2.4 输出结果
根据您的需求进行市场调研
已经给您定制好了一件大小为 XXXL 的衣服
为您提供一条龙的包办服务
5.3 动态代理的优缺点
优点:
-
代理类在运行时动态生成,避免了静态代理中每个目标类都需要一个代理类的问题。
-
代码更加灵活,可以对多个目标类进行统一代理。
缺点:
-
动态代理的实现依赖反射机制,性能相对较低。
-
代码的可读性和调试性较差。
6. 静态代理与动态代理的对比
特性 | 静态代理 | 动态代理 |
---|---|---|
代理类生成时间 | 编译时生成 | 运行时生成 |
代码量 | 较多,每个目标类需要一个代理类 | 较少,统一通过动态代理工厂生成 |
灵活性 | 较低 | 较高 |
性能 | 较高 | 较低(依赖反射机制) |
7. 总结
代理模式是 Java 开发中非常重要的设计模式,静态代理和动态代理各有优缺点,适用于不同的场景。在实际开发中,动态代理由于其灵活性和可扩展性,被广泛应用在 AOP、RPC 等领域。
通过本文的代码示例和思维导图,相信你对 Java 代理模式有了更深入的理解。希望这篇文章对你有所帮助!
如果你有任何问题或建议,欢迎在评论区留言,我们一起交流学习! 😊