深入理解Spring AOP:JDK与CGLIB代理的拦截处理

版权申诉
0 下载量 4 浏览量 更新于2024-07-08 收藏 406KB PDF 举报
"死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理" 在Spring AOP中,代理对象的创建是为了实现面向切面编程,它允许我们在不修改原有代码的情况下,向方法添加额外的功能,如日志、事务管理等。Spring支持两种代理方式:JDK动态代理和CGLIB代理。这两种代理方式在处理拦截时有所不同。 **JDK动态代理** JDK动态代理依赖于Java的反射机制,适用于目标类实现了接口的情况。在Spring中,`JdkDynamicAopProxy`是负责创建JDK代理对象的类。当一个Bean需要被代理时,Spring会生成一个实现了目标类所有接口的动态代理类。这个代理类会在调用目标方法时,通过实现`java.lang.reflect.InvocationHandler`接口的`invoke()`方法来处理拦截逻辑。 在`JdkDynamicAopProxy`的`getProxy()`方法中,Spring首先获取目标类实现的所有接口,并加上Spring的一些内部接口,然后通过`Proxy.newProxyInstance()`创建代理对象。代理对象在执行方法时,实际上会调用`InvocationHandler`的`invoke()`方法,这个方法会根据配置的Advisor找到对应的Advice(通知),并在调用目标方法前后执行相应的逻辑。 **CGLIB代理** 对于未实现接口的目标类,Spring会使用CGLIB库来创建代理对象。CGLIB是一个强大的高性能的代码生成库,它可以在运行期扩展Java类与实现Java接口。Spring中的`ObjenesisCglibAopProxy`负责创建CGLIB代理对象。CGLIB通过字节码技术生成一个目标类的子类,这个子类在运行时被动态加载,它重写了目标类的方法,从而能够在调用方法时插入切面逻辑。 在CGLIB代理中,拦截处理发生在`MethodInterceptor`的`intercept()`方法。Spring将所有的Advisor转换为`Callback`对象,这些`Callback`在代理对象调用方法时会被执行。每个`Callback`代表一个特定的拦截行为,例如`MethodInterceptor`。 **代理选择** Spring会根据目标类是否实现接口来决定使用哪种代理方式。如果目标类实现了接口,那么会选择JDK动态代理;如果没有实现接口,或者为了性能考虑,可以选择CGLIB。但需要注意的是,从Spring 5开始,如果JDK版本支持,即使目标类没有接口,Spring也会优先尝试使用JDK动态代理。 **总结** Spring AOP的两种代理方式各有优劣。JDK动态代理不需修改目标类,但要求目标类实现至少一个接口。CGLIB代理无需接口,但性能上可能略逊于JDK代理。理解这两种代理的工作原理对于深入学习Spring AOP至关重要,可以帮助我们更好地设计和优化面向切面的代码。同时,熟悉源码分析可以加深对Spring框架的理解,提升问题排查和优化的能力。