Java代理模式详解:静态代理与动态代理
需积分: 1 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`充当了代理角色,通过反射调用目标对象的方法,并在调用前后添加额外的逻辑。
总结:
静态代理和动态代理各有优缺点。静态代理易于理解,但需要为每个委托类手动编写代理类;动态代理则更加灵活,能够在运行时动态生成代理类,减少了代码量,尤其适用于接口众多的情况。然而,动态代理无法代理没有接口的类。根据项目需求和场景,开发者可以选择适合的代理实现方式。"
395 浏览量
183 浏览量
2024-06-29 上传
183 浏览量
113 浏览量
2024-12-26 上传
179 浏览量
227 浏览量
119 浏览量