欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > 一文讲解Java中AOP的底层原理

一文讲解Java中AOP的底层原理

2025/12/14 3:47:21 来源:https://blog.csdn.net/Kerwin_D/article/details/145481438  浏览:    关键词:一文讲解Java中AOP的底层原理

AOP是通过动态代理实现的,代理方式有两种:JDK动态代理和CGLIB代理

①、JDK 动态代理是基于接口的代理,只能代理实现了接口的类。

使用 JDK 动态代理时,Spring AOP 会创建一个代理对象,该代理对象实现了目标对象所实现的接口,并在方法调用前后插入横切逻辑。

优点:只需依赖 JDK 自带的 java.lang.reflect.Proxy 类,不需要额外的库;缺点:只能代理接口,不能代理类本身。

示例代码:

public interface Service {void perform();
}public class ServiceImpl implements Service {public void perform() {System.out.println("Performing service...");}
}public class ServiceInvocationHandler implements InvocationHandler {private Object target;public ServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method");Object result = method.invoke(target, args);System.out.println("After method");return result;}
}public class Main {public static void main(String[] args) {Service service = new ServiceImpl();Service proxy = (Service) Proxy.newProxyInstance(service.getClass().getClassLoader(),service.getClass().getInterfaces(),new ServiceInvocationHandler(service));proxy.perform();}
}

②、CGLIB 动态代理是基于继承的代理,可以代理没有实现接口的类。

使用 CGLIB 动态代理时,Spring AOP 会生成目标类的子类,并在方法调用前后插入横切逻辑。
在这里插入图片描述
优点:可以代理没有实现接口的类,灵活性更高;缺点:需要依赖 CGLIB 库,创建代理对象的开销相对较大。

示例代码:

public class Service {public void perform() {System.out.println("Performing service...");}
}public class ServiceInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method");Object result = proxy.invokeSuper(obj, args);System.out.println("After method");return result;}
}public class Main {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Service.class);enhancer.setCallback(new ServiceInterceptor());Service proxy = (Service) enhancer.create();proxy.perform();}
}

那么,选择CGLIB还是JDK动态代理呢?

  • 如果目标对象没有实现任何接口,则只能使用 CGLIB 代理。如果目标对象实现了接口,通常首选 JDK 动态代理。
  • 虽然 CGLIB 在代理类的生成过程中可能消耗更多资源,但在运行时具有较高的性能。对于性能敏感且代理对象创建频率不高的场景,可以考虑使用 CGLIB。
  • JDK 动态代理是 Java 原生支持的,不需要额外引入库。而 CGLIB 需要将 CGLIB 库作为依赖加入项目中。

如果继续再问下,JDK动态代理和CGLIB实际开发中怎么用呢?

假设我们有这样一个小场景,客服中转,解决用户问题:

在这里插入图片描述
①、JDK 动态代理实现:
在这里插入图片描述
第一步,创建接口

public interface ISolver {void solve();
}

第二步,实现对应接口

public class Solver implements ISolver {@Overridepublic void solve() {System.out.println("疯狂掉头发解决问题……");}
}

第三步,动态代理工厂:ProxyFactory,直接用反射方式生成一个目标对象的代理,这里用了一个匿名内部类方式重写 InvocationHandler 方法。

public class ProxyFactory {// 维护一个目标对象private Object target;public ProxyFactory(Object target) {this.target = target;}// 为目标对象生成代理对象public Object getProxyInstance() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("请问有什么可以帮到您?");// 调用目标对象方法Object returnValue = method.invoke(target, args);System.out.println("问题已经解决啦!");return null;}});}
}

第五步,客户端:Client,生成一个代理对象实例,通过代理对象调用目标对象方法

public class Client {public static void main(String[] args) {//目标对象:程序员ISolver developer = new Solver();//代理:客服小姐姐ISolver csProxy = (ISolver) new ProxyFactory(developer).getProxyInstance();//目标方法:解决问题csProxy.solve();}
}

②、CGLIB 动态代理实现:
在这里插入图片描述
第一步:定义目标类(Solver),目标类 Solver 定义了一个 solve 方法,模拟了解决问题的行为。目标类不需要实现任何接口,这与 JDK 动态代理的要求不同。

public class Solver {public void solve() {System.out.println("疯狂掉头发解决问题……");}
}

第二步:动态代理工厂(ProxyFactory),ProxyFactory 类实现了 MethodInterceptor 接口,这是 CGLIB 提供的一个方法拦截接口,用于定义方法的拦截逻辑。

public class ProxyFactory implements MethodInterceptor {//维护一个目标对象private Object target;public ProxyFactory(Object target) {this.target = target;}//为目标对象生成代理对象public Object getProxyInstance() {//工具类Enhancer en = new Enhancer();//设置父类en.setSuperclass(target.getClass());//设置回调函数en.setCallback(this);//创建子类对象代理return en.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("请问有什么可以帮到您?");// 执行目标对象的方法Object returnValue = method.invoke(target, args);System.out.println("问题已经解决啦!");return null;}}
  • ProxyFactory 接收一个 Object 类型的 target,即目标对象的实例。
  • 使用 CGLIB 的 Enhancer 类来生成目标类的子类(代理对象)。通过 setSuperclass 设置代理对象的父类为目标对象的类,setCallback 设置方法拦截器为当前对象(this),最后调用 create 方法生成并返回代理对象。
  • 重写 MethodInterceptor 接口的 intercept 方法以提供方法拦截逻辑。在目标方法执行前后添加自定义逻辑,然后通过 method.invoke 调用目标对象的方法。

第三步:客户端使用代理,首先创建目标对象(Solver 的实例),然后使用 ProxyFactory 创建该目标对象的代理。通过代理对象调用 solve 方法时,会先执行 intercept 方法中定义的逻辑,然后执行目标方法,最后再执行 intercept 方法中的后续逻辑。

public class Client {public static void main(String[] args) {//目标对象:程序员Solver developer = new Solver();//代理:客服小姐姐Solver csProxy = (Solver) new ProxyFactory(developer).getProxyInstance();//目标方法:解决问题csProxy.solve();}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com