跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Java代理模式
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Java代理模式 = '''代理模式'''(Proxy Pattern)是一种结构型设计模式,它允许通过一个代理对象控制对另一个对象的访问。代理模式常用于延迟初始化、访问控制、日志记录等场景,是Java中常见的设计模式之一。 == 简介 == 代理模式的核心思想是为某个对象提供一个代理,以控制对该对象的访问。代理对象可以在客户端和目标对象之间起到中介的作用,从而在不修改目标对象代码的情况下增强其功能。 代理模式通常分为以下三种类型: * '''静态代理''':在编译时确定代理关系。 * '''动态代理''':在运行时动态生成代理类。 * '''虚拟代理''':延迟加载目标对象,直到真正需要时才创建。 == 静态代理 == 静态代理是最简单的代理实现方式,代理类和目标类实现相同的接口,并在代理类中调用目标类的方法。 === 示例代码 === <syntaxhighlight lang="java"> // 1. 定义接口 interface Image { void display(); } // 2. 实现目标类 class RealImage implements Image { private String filename; public RealImage(String filename) { this.filename = filename; loadFromDisk(); } private void loadFromDisk() { System.out.println("Loading image: " + filename); } @Override public void display() { System.out.println("Displaying image: " + filename); } } // 3. 实现代理类 class ProxyImage implements Image { private RealImage realImage; private String filename; public ProxyImage(String filename) { this.filename = filename; } @Override public void display() { if (realImage == null) { realImage = new RealImage(filename); // 延迟加载 } realImage.display(); } } // 4. 客户端代码 public class ProxyPatternDemo { public static void main(String[] args) { Image image = new ProxyImage("test.jpg"); // 第一次调用会加载图片 image.display(); // 第二次调用直接显示,无需重新加载 image.display(); } } </syntaxhighlight> === 输出结果 === <pre> Loading image: test.jpg Displaying image: test.jpg Displaying image: test.jpg </pre> === 解释 === 1. 定义`Image`接口,包含`display()`方法。 2. `RealImage`是实际加载和显示图片的类。 3. `ProxyImage`控制对`RealImage`的访问,实现了延迟加载功能。 4. 客户端通过代理访问图片,第一次调用时才会真正加载图片。 == 动态代理 == Java动态代理利用反射机制在运行时动态创建代理类,比静态代理更灵活。主要通过`java.lang.reflect.Proxy`和`java.lang.reflect.InvocationHandler`实现。 === 示例代码 === <syntaxhighlight lang="java"> import java.lang.reflect.*; // 1. 定义接口 interface Calculator { int add(int a, int b); int subtract(int a, int b); } // 2. 实现目标类 class CalculatorImpl implements Calculator { @Override public int add(int a, int b) { return a + b; } @Override public int subtract(int a, int b) { return a - b; } } // 3. 实现InvocationHandler class LoggingHandler implements InvocationHandler { private Object target; public LoggingHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method: " + method.getName()); Object result = method.invoke(target, args); System.out.println("After method: " + method.getName()); return result; } } // 4. 客户端代码 public class DynamicProxyDemo { public static void main(String[] args) { Calculator realCalculator = new CalculatorImpl(); Calculator proxy = (Calculator) Proxy.newProxyInstance( Calculator.class.getClassLoader(), new Class[]{Calculator.class}, new LoggingHandler(realCalculator) ); System.out.println("Result: " + proxy.add(5, 3)); System.out.println("Result: " + proxy.subtract(5, 3)); } } </syntaxhighlight> === 输出结果 === <pre> Before method: add After method: add Result: 8 Before method: subtract After method: subtract Result: 2 </pre> === 解释 === 1. 定义`Calculator`接口和实现类`CalculatorImpl`。 2. `LoggingHandler`实现`InvocationHandler`,在方法调用前后添加日志。 3. 通过`Proxy.newProxyInstance()`动态创建代理对象。 4. 客户端调用代理对象的方法时,会自动调用`invoke()`方法。 == 代理模式类图 == <mermaid> classDiagram class Subject { <<interface>> +request() } class RealSubject { +request() } class Proxy { -realSubject: RealSubject +request() } Subject <|.. RealSubject Subject <|.. Proxy Proxy --> RealSubject </mermaid> == 应用场景 == 代理模式在以下场景中特别有用: * '''远程代理''':为远程对象提供本地代表(如RMI)。 * '''虚拟代理''':延迟加载大资源对象(如图片、文件)。 * '''保护代理''':控制对敏感对象的访问权限。 * '''智能引用''':在访问对象时执行额外操作(如引用计数、线程安全检查)。 == 优缺点 == === 优点 === * 职责清晰,符合单一职责原则。 * 扩展性强,可以在不修改目标对象的情况下增强功能。 * 客户端可以透明地使用代理对象。 === 缺点 === * 静态代理需要为每个服务创建代理类,工作量大。 * 动态代理使用反射,性能略低于直接调用。 * 增加了系统的复杂度。 == 进阶应用 == === Spring AOP中的代理 === Spring框架广泛使用代理模式实现AOP(面向切面编程)。Spring AOP默认使用JDK动态代理(针对接口)或CGLIB(针对类)来创建代理对象。 === 示例:Spring AOP代理 === <syntaxhighlight lang="java"> @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Before method: " + joinPoint.getSignature().getName()); } @After("execution(* com.example.service.*.*(..))") public void logAfter(JoinPoint joinPoint) { System.out.println("After method: " + joinPoint.getSignature().getName()); } } </syntaxhighlight> === 性能考虑 === 对于性能敏感的场景,可以考虑: * 缓存代理对象,避免重复创建。 * 使用字节码生成工具(如Byte Buddy)替代反射。 * 在编译时生成代理(如Annotation Processing Tool)。 == 总结 == 代理模式是Java中强大的设计模式,它通过引入代理对象来控制对目标对象的访问。无论是简单的静态代理还是灵活的动态代理,都能有效地解耦客户端和目标对象,增强系统功能。理解代理模式对于掌握Java高级特性(如Spring AOP)至关重要。 [[Category:编程语言]] [[Category:Java]] [[Category:Java设计模式]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)