静态代理和动态代理的区别,什么场景使用

静态代理和动态代理的区别

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)的核心技术之一,提供了极大的灵活性和扩展性。

posted @ 2025-08-20 20:34  一刹流云散  阅读(23)  评论(0)    收藏  举报