🔷静态代理
- 创建UserService接口
java
package com.zr.proxy.staticProxy;
/**
* @Author: zr
* @Date: 2025/11/06/13:49
* @Description:
*/
public interface UserService {
void addUser();
}
- 创建UserServiceImpl,实现UserService接口
java
package com.zr.proxy.staticProxy;
/**
* @Author: zr
* @Date: 2025/11/06/13:49
* @Description:
*/
public class UserServiceImpl implements UserService{
@Override
public void addUser() {
System.out.println("addUser方法执行了");
}
}
- 创建静态代理同时也实现UserService接口,
在重写addUser方法时候将原来的实现类UserServiceImpl也引入,
在原来的实现类UserServiceImpl方法执行前后执行前置和后置方法
java
package com.zr.proxy.staticProxy;
/**
* @Author: zr
* @Date: 2025/11/06/13:50
* @Description:
*/
public class UserServiceProxy implements UserService{
private final UserService target;
public UserServiceProxy(UserService target) {
this.target = target;
}
@Override
public void addUser() {
System.out.println("【前置】检查权限");
target.addUser();
System.out.println("【后置】记录日志");
}
public static void main(String[] args) {
UserService target = new UserServiceImpl();
UserService proxy = new UserServiceProxy(target);
proxy.addUser();
}
}
- 测试结果

🔥JDK动态代理
- UserService和UserServiceImpl复用静态代理的
- 创建JdkProxy JDK动态代理
- 实现InvocationHandler
- 重写invoke方法
- 通过newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)获取代理对象
- 强转为代理对象正真的类型UserService
java
package com.zr.proxy.jdkProxy;
import com.zr.proxy.staticProxy.UserService;
import com.zr.proxy.staticProxy.UserServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author: zr
* @Date: 2025/11/06/14:15
* @Description:
*/
public class JdkProxy implements InvocationHandler {
private final Object target;
public JdkProxy(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 static void main(String[] args) {
UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JdkProxy(target));
proxy.addUser();
}
}
- 测试结果

🔷CGLIB
- 引入依赖,使用 Spring 的 cglib(spring-core 内置 ASM 9+),如果JDK17直接用cglib的包会报错
java
<!-- <dependency>-->
<!-- <groupId>cglib</groupId>-->
<!-- <artifactId>cglib</artifactId>-->
<!-- <version>3.3.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.30</version>
</dependency>
- 创建一个需要代理的类
java
package com.zr.proxy.cglibProxy;
/**
* @Author: zr
* @Date: 2025/11/06/14:24
* @Description:
*/
public class OrderService {
public void createOrder() {
System.out.println("执行 createOrder()");
}
}
- 实现Cglib动态代理
- 实现MethodInterceptor
- 新增一个公共方法getProxy通过Enhancer.create(Class type, Callback callback)获取代理对象
- 重写intercept方法,在重写的方法中对被代理的对象的方法实现功能增强
- 测试方法中通过new CglibProxy(orderService).getProxy()获取代理对象
- 强转为代理对象正真的类型OrderService
java
package com.zr.proxy.cglibProxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Author: zr
* @Date: 2025/11/06/14:24
* @Description:
*/
public class CglibProxy implements MethodInterceptor {
private final Object target;
public CglibProxy(Object target) {
this.target = target;
}
public Object getProxy(){
return Enhancer.create(target.getClass(), this);
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("【前置】校验参数");
Object result = methodProxy.invoke(target, objects);
System.out.println("【后置】记录日志");
return result;
}
public static void main(String[] args) {
OrderService orderService = new OrderService();
OrderService proxy = (OrderService) new CglibProxy(orderService).getProxy();
proxy.createOrder();
}
}
- 测试

🙅在 JDK 17 里直接使用 CGLIB 3.3.0 会报模块访问限制异常。

报错核心内容:
plain
InaccessibleObjectException: module java.base does not "opens java.lang"
❗报错原因
JDK 9+ 模块化后,java.lang.ClassLoader.defineClass() 不能随便通过反射访问,所以 老版 CGLIB 无法工作。
😃解决方案
换成 Spring 自带的 CGLIB(推荐,不需要 opens), Spring 早就把 CGLIB 升级为能兼容 JDK 17 的版本,所以不会出这个问题。
使用 Spring 的 cglib(spring-core 内置 ASM 9+),兼容 JDK 17、21:
在 Maven 中添加:
xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.30</version>
</dependency>
👉总结
🔹对比
| 对比项 | 静态代理 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|---|
| 是否需要接口 | ✅ 必须有接口 | ✅ 必须有接口 | ❌ 不需要接口(基于继承) |
| 代理类是否手写 | ✅ 要自己写代理类 | ❌ 自动生成代理类 | ❌ 自动生成子类作为代理 |
| 代理实现方式 | 写死逻辑 | 反射 + Proxy API | ASM 字节码改写,生成子类 |
| 性能 | 中等 | 中等偏下 | ✅ 较高(比 JDK 快) |
| 能否代理 final 类/方法 | ✅ 可以 | ✅ 可以(接口层代理) | ❌ 不能代理 final class 或 final method |
| 框架支持情况 | 基本不用 | Spring AOP 默认策略 | Spring AOP 无接口时使用 |
| 代码量 | 多,麻烦 | 少 | 少 |
| 适用场景 | 小项目、简单增强 | 面向接口编程时增强 | 无接口的类,如 Controller、Service |
🧩个人总结
- 静态代理:人为写代理类,麻烦但最直观。
- ** 一个接口写一个代理类,太累,而动态代理在运行时自动生成。**
- JDK 动态代理:依赖接口,运行时生成代理类(Proxy)。
- ** 要求目标类必须实现接口,通过反射实现代理。,否则用不了。 **
- CGLIB 动态代理:不需要接口,运行时生成子类(Enhancer)。
- ** 不需要接口,通过生成目标类的子类实现代理,因此无法代理 final 类和方法。**
- Spring AOP 默认使用 JDK 动态代理,若没有接口则切换为 CGLIB。