静态代理 & 动态代理:实战运用 + 场景区别 + 怎么选

我不讲空话,直接讲什么时候用、怎么用、为什么用、项目里怎么写 ,让你彻底懂运用


一、先一句话分清:静态 vs 动态

静态代理:手写代理类 → 一个目标类配一个代理

动态代理:自动生成代理 → 一个通用代理,增强所有类


二、静态代理(运用场景 + 实战代码)

1. 运用场景(什么时候用?)

  • 类很少、固定不变
  • 简单增强、不需要通用
  • 只想理解代理原理
  • 项目几乎不用,因为类会爆炸

2. 实战运用:给业务方法加日志

① 接口

java 复制代码
public interface UserService {
    void addUser();
}

② 目标类(真正业务)

java 复制代码
public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("执行添加用户业务");
    }
}

③ 静态代理类(手动编写

java 复制代码
public class UserServiceProxy implements UserService {
    private UserService target;

    public UserServiceProxy(UserService target) {
        this.target = target;
    }

    @Override
    public void addUser() {
        System.out.println("【日志】方法开始"); // 增强
        target.addUser(); // 调用目标
        System.out.println("【日志】方法结束"); // 增强
    }
}

④ 使用

java 复制代码
public class Test {
    public static void main(String[] args) {
        UserService service = new UserServiceImpl();
        UserService proxy = new UserServiceProxy(service); // 静态代理
        proxy.addUser();
    }
}

3. 静态代理的优点

  • 简单、直观、好理解
  • 不依赖反射

4. 静态代理缺点(致命)

  • 一个类就要写一个代理类
  • 100 个业务类 → 100 个代理类 → 类爆炸
  • 无法通用、无法统一增强

三、动态代理(项目 99% 都用它

1. 运用场景(核心!背下来)

  • 统一日志
  • 统一权限校验
  • 事务管理(@Transactional)
  • 缓存增强(@Cacheable)
  • 异步执行(@Async)
  • 限流、熔断、监控
  • AOP 面向切面编程
  • RPC 远程调用

一句话: 需要给很多方法统一加功能,又不想改源码 → 必须动态代理!


四、JDK 动态代理(必须有接口)实战运用

核心:一个工具类,增强所有接口实现类

java 复制代码
public class JdkProxyFactory {
    public static Object getProxy(Object target) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    // 前置增强
                    System.out.println("日志开始:" + method.getName());
                    
                    // 执行目标方法
                    Object result = method.invoke(target, args);
                    
                    // 后置增强
                    System.out.println("日志结束");
                    return result;
                });
    }
}

使用:

java 复制代码
UserService service = new UserServiceImpl();
UserService proxy = (UserService) JdkProxyFactory.getProxy(service);
proxy.addUser();

优点:

  • 通用!所有接口都能用
  • 不写大量代理类
  • Spring AOP 底层就是它

五、CGLIB 动态代理(没有接口也能代理

运用场景:

  • 类没有实现接口
  • 要代理普通类
  • Spring 默认无接口时用它

核心代码:

java 复制代码
public class CglibProxyFactory {
    public static Object getProxy(Class<?> clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
            System.out.println("cglib 日志开始");
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("cglib 日志结束");
            return result;
        });
        return enhancer.create();
    }
}

六、最关键:静态 / 动态代理到底怎么运用?(项目实战指南)

1. 静态代理运用场景

  • 教学、理解原理
  • 极简单、固定不变的小功能
  • 企业项目基本不用

2. 动态代理运用场景(必须掌握)

  • 统一日志
  • 统一权限
  • 事务
  • 缓存
  • AOP
  • 限流、监控、分布式锁
  • 微服务网关、RPC

3. JDK 动态代理运用

  • 目标类有接口
  • 性能更好
  • Spring 首选

4. CGLIB 动态代理运用

  • 目标类没有接口
  • Spring 会自动用它

七、最强总结(面试 + 工作 直接背)

静态代理

  • 手写代理
  • 一对一
  • 简单但无法通用
  • 只用于学习

动态代理

  • 运行时自动生成
  • 一对多
  • 通用增强所有类
  • Spring AOP、事务、缓存、权限全靠它
  • 项目真正运用的技术

一句话终极运用口诀

简单固定用静态,通用增强用动态; 有接口用 JDK,无接口用 CGLIB; 日志事务缓存权,全靠动态代理实现!

相关推荐
Lhan.zzZ5 分钟前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
心平气和量大福大25 分钟前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
码哥DFS39 分钟前
构造函数、实例对象、对象原型 ----三者关系
开发语言·javascript·原型模式
952361 小时前
Spring-cloud配置中心
java·spring·spring cloud·微服务
quantdash_cc1 小时前
告别自建 Requests/BS4 网页爬虫:基于 QuantDash 搭建零维保的高性能量化行情流水线
开发语言·爬虫·python·pandas·量化·quantdash
ydd1001001 小时前
寻找两个正序数组的中位数 Java 题解,二分分割详解
java·开发语言
半亩码田2 小时前
C#转Python第3.1篇:Python 的 class 没有访问修饰符?面向对象的另一条路
开发语言·python·c#
真上帝的左手2 小时前
10. 软件设计&架构-Spring Security 7 整合CAS SSO 单点登录
java·spring·架构·sso
Wzx1980122 小时前
python沙箱和docker沙箱你选对了吗?
开发语言·python·docker
牧羊人.3333 小时前
Python 办公自动化从入门到入土|09 数据容器之字典
开发语言·python