静态代理和动态代理的区别,什么场景使用
静态代理和动态代理的区别
1. 基本概念
静态代理
- 代理类在编译时就已经确定
- 需要手动编写代理类代码
- 代理类和目标类实现相同的接口
动态代理
- 代理类在运行时动态生成
- 不需要手动编写代理类
- 通过反射机制创建代理对象
2. 代码实现对比
静态代理示例
// 共同接口
interface Service {
void performTask();
}
// 目标类
class RealService implements Service {
@Override
public void performTask() {
System.out.println("执行实际任务");
}
}
// 静态代理类(需要手动编写)
class StaticProxy implements Service {
private Service target;
public StaticProxy(Service target) {
this.target = target;
}
@Override
public void performTask() {
System.out.println("前置处理");
target.performTask();
System.out.println("后置处理");
}
}
// 使用
Service service = new StaticProxy(new RealService());
service.performTask();
动态代理示例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 动态代理处理器
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("前置处理");
Object result = method.invoke(target, args);
System.out.println("后置处理");
return result;
}
// 创建代理对象的工厂方法
public <T> T getProxy(Class<T> interfaceClass) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
}
// 使用
Service realService = new RealService();
Service proxyService = new DynamicProxyHandler(realService).getProxy(Service.class);
proxyService.performTask();
3. 主要区别对比
| 特性 | 静态代理 | 动态代理 |
|---|---|---|
| 代理类创建时机 | 编译时手动编写 | 运行时动态生成 |
| 代码量 | 需要为每个接口编写代理类 | 只需一个代理处理器 |
| 维护成本 | 高(接口增加方法需修改代理类) | 低(自动适配接口变化) |
| 性能 | 较高(无反射开销) | 较低(存在反射开销) |
| 灵活性 | 低 | 高 |
4. 适用场景
静态代理适用场景
- 简单场景:代理逻辑简单且固定
- 性能敏感:对性能要求较高的场景
- 明确接口:接口稳定且数量较少
- 学习目的:理解代理模式的基本原理
动态代理适用场景
- AOP框架:如Spring AOP实现
- RPC框架:远程方法调用代理
- 日志记录:统一为多个服务添加日志
- 权限控制:统一进行权限验证
- 事务管理:统一进行事务控制
- 缓存处理:统一进行缓存操作
5. Spring中的应用示例
// Spring AOP中的动态代理应用
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("方法执行前: " + joinPoint.getSignature().getName());
}
@After("execution(* com.example.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("方法执行后: " + joinPoint.getSignature().getName());
}
}
6. 总结
选择建议:
- 如果代理逻辑简单且接口固定,可以选择静态代理
- 如果需要为大量接口提供统一代理逻辑,应选择动态代理
- 在企业级应用中,动态代理更为常用,特别是配合AOP使用
动态代理是现代Java框架(如Spring)的核心技术之一,提供了极大的灵活性和扩展性。

浙公网安备 33010602011771号