如有错误欢迎指出
是jdk动态代理是从一步步开始写完
| 特性/维度 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
| 是否需要接口 | ✅ 需要接口 | ❌ 不需要接口(可代理普通类) |
| 代理原理 | 基于反射实现接口方法的代理 | 继承目标类并重写方法,基于 ASM 字节码操作 |
| 代理类结构 | 生成实现目标接口的代理类 | 生成子类(目标类的子类) |
| 性能(启动时) | 创建代理类较快 | 创建代理类稍慢(涉及字节码操作) |
| 性能(执行时) | 方法调用稍慢(反射) | 方法调用较快(直接调用子类方法) |
| 适合场景 | 有接口的服务类,如 Service 接口层 | 没有接口的类,或对性能要求较高的场景 |
| 常用框架支持 | Spring AOP 默认使用 JDK Proxy(有接口时) | Spring AOP 在无接口时使用 CGLIB |
| 类或方法限制 | 接口方法都能代理 | final 类或 final 方法不能被代理 |
| 生成方式 | Proxy.newProxyInstance() |
Enhancer.create()(来自 CGLIB) |
| 配置示例(Spring) | <aop:aspectj-autoproxy/>(默认) |
配合 <aop:aspectj-autoproxy proxy-target-class="true"/> |

https://www.doubao.com/thread/w25860ff971baf089
java proxy增强
java
public class JdkProxyDemo {
interface Foo {
void foo();
int bar();
}
static final class Target implements Foo {
public void foo() {
System.out.println("target foo");
}
public int bar() {
System.out.println("target bar");
return 100;
}
}
// jdk 只能针对接口代理
// cglib
public static void main(String[] param) throws IOException {
// 目标对象
Target target = new Target();
///获取类加载器
ClassLoader loader = JdkProxyDemo.class.getClassLoader();
// 创建代理对象
Foo proxy = (Foo) Proxy.newProxyInstance(
loader, // 类加载器
new Class[]{Foo.class}, // 代理类需要实现的接口
new InvocationHandler() { // 方法调用处理器
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before..."); // 方法调用前的增强逻辑
Object result = method.invoke(target, args); // 调用目标对象的方法
System.out.println("after...."); // 方法调用后的增强逻辑
return result; // 返回目标方法的执行结果
}
}
);
proxy.foo();
proxy.bar();
}
}
before...
target foo
after....
before...
target bar
after....
java
public static Object newProxyInstance(ClassLoader loader,//加载器
Class<?>[] interfaces, ///实现的接口
InvocationHandler h)
throws IllegalArgumentException
{
}
java
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) //代理逻辑
throws Throwable;
}
java cglib Enhancer代理增强
继承父类实现
java
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyDemo {
static class Target {
public void foo() {
System.out.println("target foo too");
}
}
public static void main(String[] args) {
// 使用 CGLIB 创建代理对象
Target proxy = (Target) Enhancer.create(Target.class, new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
// 方式 1:反射调用目标对象方法(性能较差)
// Object result = method.invoke(new Target(), args);
// 方式 2:使用 methodProxy.invokeSuper() 调用父类方法(CGLIB 方式,性能更好)
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("after...");
return result;
}
});
// 调用代理方法
proxy.foo();
}
}
jdk 反射源码探究
第一个版本
代理类
java
public class A01proxy {
interface Foo{
void foo();
}
public static class Target implements Foo{
@Override
public void foo()
{
System.out.println("Target.foo()");
}
}
public static void main(String[] args)
{
Foo Proxy = new Proxyq();
Proxy.foo();
}
}
java
public class Proxyq implements A01proxy.Foo {
@Override
public void foo() {
System.out.println("foo");
new Target().foo();
}
}
java
foo
Target.foo()
Target.foo()]()
//类似于什么设计模式呢
缺点-代理的方法直接写死到内部,如果要新增很麻烦
版本2
优化点解耦 -让代理的方法交给外部来写
新增接口-使得逻辑再外部使用时实现
接口
java
public interface InvocationHandler {
void invoke();
}
java
public class Proxyq implements A01proxy.Foo {
private InvocationHandler h;
public Proxyq(com.itheima.a13.a02.InvocationHandler foo) {
this.h = foo;
}
@Override
public void foo() {
h.invoke();
}
}
java
public class A01proxy {
interface Foo{
void foo();
}
public static class Target implements Foo{
@Override
public void foo()
{
System.out.println("Target.foo()");
}
}
public static void main(String[] args)
{
//外部实现
Foo Proxy = new Proxyq(new InvocationHandler(){
@Override
public void invoke() {
System.out.println("foo");
new Target().foo();
}
});
Proxy.foo();
}
}
缺点
如果是boo方法想代理呢,那么就会出现错误。(Method method)需要传递调用的方法来动态调用
Proxy.boo()不知道怎么处理。
三 优化方法过多无法处理
java
public interface InvocationHandler {
void invoke(Method method, Object[] args) throws InvocationTargetException, IllegalAccessException;
}
我们从源码中看到就是这样,我们来实现一下
java
public class A01proxy {
interface Foo{
void foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
void bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
}
public static class Target implements Foo{
@Override
public void foo()
{
System.out.println("Target.foo()");
}
@Override
public void bar() {
System.out.println("Target.bar()");
}
}
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Foo Proxy = new Proxyq(new InvocationHandler(){
@Override
public void invoke(Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println("before");
method.invoke(new Target(), args); ///反射
}
});
Proxy.foo();
Proxy.bar();
}
}
java
public interface InvocationHandler {
void invoke(Method method, Object[] args) throws InvocationTargetException, IllegalAccessException;
}
java
public class Proxyq implements A01proxy.Foo {
private InvocationHandler h;
public Proxyq(InvocationHandler foo) {
this.h = t;
}
@Override
public void foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
System.out.println("Proxyq.foo()");
Method foo= A01proxy.Foo.class.getMethod("foo");//反射
h.invoke( foo,new Object[0]);//执行
}
@Override
public void bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
System.out.println("Proxyq.bar()");
Method bar= A01proxy.Foo.class.getMethod("bar");
h.invoke(bar,new Object[0]);
}
}
反射拿去了方法
缺点,拿不到返回值
优化 3.1返回值处理
java
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Foo Proxy = new Proxyq(new InvocationHandler(){
@Override
public Object invoke(Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {//返回值处理
System.out.println("before");
return method.invoke(new Target(), args);
}
});
Proxy.foo();
Proxy.bar();
}
java
public interface InvocationHandler {
Object invoke(Method method, Object[] args) throws InvocationTargetException, IllegalAccessException;
}
java
@Override
public void foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
System.out.println("Proxyq.foo()");
Method foo= A01proxy.Foo.class.getMethod("foo");
Object result= h.invoke( foo,new Object[0]);
//这里需要return,但是我没有处理
}
优化 保存与jdk一致
新增参数object->吧代理类传到实现里面去了

异常处理
注意异常顺序

代码优化
///防止多次反射拿去method

最终
java
public class $Proxy0 implements test01.Foo { //代理类
test01.InvocationHandler h;
public $Proxy0(test01.InvocationHandler h)
{
this.h = h;
}
static Method foo;
static Method bar;
static {
try {
foo = test01.Foo.class.getMethod("foo");
bar = test01.Foo.class.getMethod("bar");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
//代理方法
@Override
public void foo() {
try {
h.invoke(this, foo, new Object[0]);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public int bar() {
try {
Object result = h.invoke(this, bar, new Object[0]);
return (int) result;
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
java
public class test01 {
interface Foo {
void foo();
int bar();
}
static class Target implements Foo {
public void foo() {
System.out.println("target foo");
}
@Override
public int bar() {
System.out.println("target bar");
return 100;
}
}
interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
public static void main(String[] param) {
Foo proxy = new $Proxy0(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 1. 功能增强
System.out.println("before...");
//2.调用方法
Object result = method.invoke(new Target(), args);
return result;
}
});
proxy.foo();
proxy.bar();
}
}
真实源码
由编译器生成的吗,还是java语法特性
JVM 在运行期生成 $Proxy 类
运行期
java
public class A12 {
interface Foo {
void foo();
int bar();
}
static class Target implements Foo {
public void foo() {
System.out.println("target foo");
}
@Override
public int bar() {
System.out.println("target bar");
return 100;
}
}
/*interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}*/
public static void main(String[] param) throws IOException {
Foo proxy = new $Proxy0(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
// 1. 功能增强
System.out.println("before...");
// 2. 调用目标
// new Target().foo();
return method.invoke(new Target(), args);
}
});
System.out.println(proxy.getClass().getName());
proxy.foo();
proxy.bar();
System.in.read();
/*
学到了什么: 代理一点都不难, 无非就是利用了多态、反射的知识
1. 方法重写可以增强逻辑, 只不过这【增强逻辑】千变万化, 不能写死在代理内部
2. 通过接口回调将【增强逻辑】置于代理类之外
3. 配合接口方法反射(也是多态), 就可以再联动调用目标方法
*/
}
}



jdk代理字节码生成
asm技术-动态生成字节码文件
jdk反射优化
反射调用次数过程
先用 Native 实现应对低频调用。
检测到高频调用后再生成字节码类(
GeneratedMethodAccessor),让反射调用性能接近普通方法调用。

- 访问器类型 表示 JVM 在不同阶段使用的
MethodAccessor实现。- 红圈标的
TestMethodInvoke.foo((int)c))说明 JVM 已经把反射"编译"成了直接调用。- 这种生成类只在高频调用的情况下才会出现,目的是避免一开始就生成大量类浪费内存。

cglib原理
介绍
CGLIB(Code Generation Library)是一个基于 ASM 的字节码生成库,用来在运行期生成类。
它可以在运行期为某个类创建一个子类代理,从而实现方法拦截(AOP)。
JDK 动态代理只能代理 接口。
Spring 的很多 bean 没有实现接口,所以需要使用:
- CGLIB 生成一个子类去做代理。
例如:
java
class UserService { ... }
↓
class UserService$$EnhancerByCGLIB extends UserService { ... }
然后把你原来对象的功能"增强"。
CGLIB 的核心构成只有两点:
继承目标类生成子类
CGLIB 通过 ASM 动态生成一个子类
子类中重写目标类的非 final 方法
在重写方法中调用拦截器
MethodInterceptor
MethodInterceptor.intercept() 做方法增强
代理类方法 → MethodInterceptor.intercept()
你可以在 intercept 里:
- 加日志
- 加权限校验
- 加事务
- 加耗时统计
然后决定是否:
- 调用父类原方法(proxy.invokeSuper)
- 不调用原方法(拦截)
- 修改参数
- 修改返回值
CGLIB 的调用链(非常关键)
假设目标类:
java
class Service {
void save() { ... }
}
CGLIB 会生成:
java
class Service$$EnhancerByCGLIB extends Service {
@Override
void save() {
// 调用拦截器
interceptor.intercept(this, saveMethod, args, methodProxy);
}
}
java
serviceProxy.save()
↓
intercept(proxyObj, method, args, methodProxy)
↓
methodProxy.invokeSuper(proxyObj, args)
↓
父类 Service.save()
MethodProxy 的作用(面试常问)
java
CGLIB 为每个方法创建一个 MethodProxy,它负责:
绑定代理类方法与父类方法的映射
在调用父类方法时使用 FastClass(避免反射)
提供 invokeSuper 方法跳过代理逻辑
java
method.invoke() → 反射 → 慢
methodProxy.invokeSuper() → FastClass → 快
FastClass 原理(提高性能的关键)
CGLIB 会为类生成一个 "FastClass",把方法调用变成整数索引:
java
methodIndex = 3
switch(3):
case 3: return obj.save()
避免使用反射,性能大幅提升。
JDK 动态代理无法达到这个性能。
java
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Target.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy)
throws Throwable {
System.out.println("before...");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after...");
return result;
}
});
Target proxy = (Target) enhancer.create();
proxy.save();
CGLIB = 运行期生成子类 + 重写方法 + 拦截调用 + FastClass 加速
代码
有字段:没问题,CGLIB 会继承它们。
构造函数不执行:字段初始化可能不完整。
final/private/static 方法无法被增强。
如果字段依赖构造注入,可能出现 null。
继承方法
步骤 操作 代码示例 说明 1 获取 Class对象Class<?> clazz = Target.class;反射的入口,拿到类的元数据。也可以用 Class.forName("包名.Target")。2 获取 Method对象Method m = clazz.getMethod("save");通过方法名和参数类型,获取 public方法。若方法是私有的或非public,用getDeclaredMethod。3 创建目标对象实例 Target obj = new Target();如果要调用实例方法,需要先有对象。静态方法可以直接传 null调用。4 调用方法 m.invoke(obj);invoke第一个参数是目标对象,后面是方法参数。5 处理异常 NoSuchMethodException、IllegalAccessException、InvocationTargetException反射涉及多种检查型异常,需要捕获或抛出。

初始化了 反射拿取了方法-同时创建了一个能够在运行期执行"原始方法/父类方法" 的快速调用器(invocation helper)。
java
save0Proxy = MethodProxy.create(
Target.class, // 被代理的类
Proxy.class, // 代理类(由 CGLIB 生成的子类)
"()V", // 方法签名(这里是无参、void 返回值)
"save", // 原方法名
"saveSuper" // 父类方法名(或调用原始实现的方法名)
);
| 步骤 | 反射 (Method.invoke) 做法 |
CGLIB (MethodProxy.invoke) 做法 |
速度差异原因 |
|---|---|---|---|
| 1. 定位方法 | 运行时查找 Method 对象(Class.getMethod) |
MethodProxy.create(...) 时直接生成代理类字节码,方法引用是编译进字节码的 |
反射是运行时查找,CGLIB 是类加载时就确定好 |
| 2. 访问权限检查 | 每次调用都会做 Method 的访问修饰符检查(JVM 安全检查) |
CGLIB 生成的子类直接调用 super.save(),不触发反射的安全检查 |
避免了重复安全检查 |
| 3. 参数传递 | invoke 内部用 Object 数组拆装参数(装箱/拆箱) |
CGLIB 生成的方法直接用原始参数类型传递(例如直接 void save() 调用) |
避免了装箱拆箱和类型转换 |
| 4. 方法调用 | JVM 通过反射调用 MethodAccessor 的 invoke 方法,间接层多 |
CGLIB 代理类直接发起 super.save() 的字节码调用 |
少了中间调用层,直接走 invokevirtual 或 invokespecial |
| 5. 调用父类实现 | 需要反射再找父类的 Method |
已在 create 时绑定 "saveSuper" 方法,生成字节码直接调用 |
直接调用字节码方法引用 |
| 最终效果 | 每次调用都走反射 API,动态解析 | 调用时和普通方法几乎一样快(接近直接调用速度) | 大幅减少运行期开销 |
create(...) 这一步,CGLIB 就会用 ASM 动态生成一个 Proxy.class 子类,并且在字节码里写死类似:
java
public void save() {
// 先执行增强逻辑...
super.save(); // 直接字节码调用
}
这样后续 invoke 调用的时候,就直接跳到字节码方法 ,完全绕过了 Method.invoke 的反射路径。
后续只需调用即可

java
Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 增强逻辑前置,如日志、权限校验
System.out.println("方法调用前增强");
// 通过 proxy 调用父类原始方法
Object result = proxy.invokeSuper(obj, args);
// 增强逻辑后置,如事务提交、日志记录
System.out.println("方法调用后增强");
return result;
}
// CGLIB 动态生成的代理类里,invokeSuper 实际上是跳过代理直接调用父类方法
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
// obj 是代理对象,调用父类(Target)的 save 方法,传入参数 args
// 这里调用的是类似 JVM 指令 invokespecial,直接调用父类实现,避免代理递归
return invokeParentMethod(obj, "save", args);
}
- intercept 是代理切入点
- invokeSuper 是跳过代理类,直接调用父类方法的快速路径
- CGLIB 使用 FastClass 避免反射,提高性能
- invokeSuper 用 invokespecial 指令调用父类实现,防止递归

走两个 一个反射调用 一个代理类调用
java
before...
save()
before...
save(int)
before...
save(long)
cglib 无反射原理
代理类调用避免反射

重写该fastclass.class- invoke 方法
fastclass
java
public class TargetFastClass {
//创建方法签名
static Signature s0 = new Signature("save", "()V");
static Signature s1 = new Signature("save", "(I)V");
static Signature s2 = new Signature("save", "(J)V");
// 获取目标方法的编号
/*
Target
save() 0
save(int) 1
save(long) 2
signature 包括方法名字、参数返回值
*/
public int getIndex(Signature signature) {
if (s0.equals(signature)) {
return 0;
} else if (s1.equals(signature)) {
return 1;
} else if (s2.equals(signature)) {
return 2;
}
return -1;
}
// 根据方法编号, 正常调用目标对象方法
public Object invoke(int index, Object target, Object[] args) {
if (index == 0) {
((Target) target).save();
return null;
} else if (index == 1) {
((Target) target).save((int) args[0]);
return null;
} else if (index == 2) {
((Target) target).save((long) args[0]);
return null;
} else {
throw new RuntimeException("无此方法");
}
}
public static void main(String[] args) {
TargetFastClass fastClass = new TargetFastClass();
int index = fastClass.getIndex(new Signature("save", "(I)V"));
System.out.println(index);
fastClass.invoke(index, new Target(), new Object[]{100});
}
}
代理方法 继承了原始类

java
public class ProxyFastClass {
static Signature s0 = new Signature("saveSuper", "()V");
static Signature s1 = new Signature("saveSuper", "(I)V");
static Signature s2 = new Signature("saveSuper", "(J)V");
// 获取代理方法的编号
/*
Proxy
saveSuper() 0
saveSuper(int) 1
saveSuper(long) 2
signature 包括方法名字、参数返回值
*/
public int getIndex(Signature signature) {
if (s0.equals(signature)) {
return 0;
} else if (s1.equals(signature)) {
return 1;
} else if (s2.equals(signature)) {
return 2;
}
return -1;
}
// 根据方法编号, 正常调用目标对象方法
public Object invokeSuper(int index, Object proxy, Object[] args) {
if (index == 0) {
((Proxy) proxy).saveSuper();
return null;
} else if (index == 1) {
((Proxy) proxy).saveSuper((int) args[0]);
return null;
} else if (index == 2) {
((Proxy) proxy).saveSuper((long) args[0]);
return null;
} else {
throw new RuntimeException("无此方法");
}
}
public static void main(String[] args) {
ProxyFastClass fastClass = new ProxyFastClass();
int index = fastClass.getIndex(new Signature("saveSuper", "()V"));
System.out.println(index);
fastClass.invokeSuper(index, new Proxy(), new Object[0]);
}
}
区别
一个调用16次后进行一个方法一个代理的避免反射
一个就是两个代理类,避免反射 -代理类中的invoke是调用了原始方法-继承写的