Java代理模式详解:静态代理与动态代理

需积分: 1 0 下载量 71 浏览量 更新于2024-09-15 1 收藏 39KB DOC 举报
"Java的静态代理和动态代理是两种实现代理模式的方法,它们允许在不修改原有代码的情况下,增加额外的功能或控制对真实对象的访问。代理模式在软件设计中广泛应用,例如数据验证、事务管理、日志记录等。本文将详细介绍这两种代理方式及其工作原理。 一、代理模式概述 代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理类作为委托类的中介,可以在调用实际业务逻辑之前和之后添加额外的操作,如日志记录、权限检查等。代理类和委托类通常具有相同的接口,使得客户端可以透明地使用代理类,而无需关心其实现细节。 二、静态代理类 静态代理是在编译期间就确定了代理关系,程序员需要手动编写代理类和委托类。在程序运行前,代理类的字节码文件(.class)已经存在。以下是一个简单的静态代理示例: 1. 定义接口`HelloService`: ```java package proxy; public interface HelloService { public String echo(String msg); public Date getTime(); } ``` 2. 创建委托类`HelloServiceImpl`实现`HelloService`接口: ```java package proxy; import java.util.Date; public class HelloServiceImpl implements HelloService { public String echo(String msg) { return "echo: " + msg; } public Date getTime() { return new Date(); } } ``` 3. 编写代理类`HelloServiceProxy`,同样实现`HelloService`接口,通过持有委托类的引用来调用其方法: ```java package proxy; public class HelloServiceProxy implements HelloService { private HelloService helloServiceImpl = new HelloServiceImpl(); public String echo(String msg) { System.out.println("代理类在调用echo方法前"); String result = helloServiceImpl.echo(msg); System.out.println("代理类在调用echo方法后"); return result; } public Date getTime() { System.out.println("代理类在调用getTime方法前"); Date result = helloServiceImpl.getTime(); System.out.println("代理类在调用getTime方法后"); return result; } } ``` 在静态代理中,`HelloServiceProxy`在调用`HelloServiceImpl`的方法前后添加了额外的打印操作,这就是代理类对委托类进行预处理和事后处理的体现。 三、动态代理类 动态代理则在程序运行时通过反射机制创建,无需预先编写代理类的源代码。Java的`java.lang.reflect.InvocationHandler`接口和`java.lang.reflect.Proxy`类提供了实现动态代理的能力。 1. 定义一个`InvocationHandler`实现类,用于处理代理对象的调用: ```java package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxyHandler implements InvocationHandler { private Object target; public DynamicProxyHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("动态代理在调用" + method.getName() + "方法前"); Object result = method.invoke(target, args); System.out.println("动态代理在调用" + method.getName() + "方法后"); return result; } public static Object getProxyInstance(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new DynamicProxyHandler(target) ); } } ``` 2. 使用`DynamicProxyHandler.getProxyInstance()`创建动态代理对象并调用方法: ```java HelloService dynamicProxy = (HelloService) DynamicProxyHandler.getProxyInstance(new HelloServiceImpl()); dynamicProxy.echo("Hello World"); dynamicProxy.getTime(); ``` 在动态代理中,`DynamicProxyHandler`充当了代理角色,通过反射调用目标对象的方法,并在调用前后添加额外的逻辑。 总结: 静态代理和动态代理各有优缺点。静态代理易于理解,但需要为每个委托类手动编写代理类;动态代理则更加灵活,能够在运行时动态生成代理类,减少了代码量,尤其适用于接口众多的情况。然而,动态代理无法代理没有接口的类。根据项目需求和场景,开发者可以选择适合的代理实现方式。"