Spring的 AOP底层用到两种代理机制
JDK 的动态代理:针对实现了接口的类产生代理。
CGlib 的动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术 生成当前类的子类对象
JDK动态代理实现
1. 创建接口和对应实现类
1 public interface UserService { 2 void login(); 3 void loginOut(); 4 }
1 //实现类 2 public class UserServiceImpl implements UserService { 3 public void login() { 4 System.out.println("login方法触发"); 5 } 6 public void loginOut() { 7 System.out.println("loginOut方法触发"); 8 } 9 }
2.创建动态代理类
1 public class PerformHandler implements InvocationHandler { 2 private Object target; //目标对象 3 public PerformHandler(Object target){ 4 this.target = target; 5 } 6 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 7 //本方法中的其他输出输入增强 8 System.out.println("方法触发了"); 9 //执行被代理类 原方法 10 Object invoke = method.invoke(target, args); 11 System.out.println("执行完毕了"); 12 return invoke; 13 } 14 }
测试
1 @Test 2 public void test1(){ 3 //测试JDK动态代理技术 4 UserService userService = new UserServiceImpl(); 5 PerformHandler performHandler = new PerformHandler(userService); 6 userService = (UserService) 7 Proxy.newProxyInstance(userService.getClass().getClassLoader(), 8 userService.getClass().getInterfaces(), 9 performHandler 10 ); 11 userService.login(); 12 }
测试结果: 在调用接口方法的前后都会添加代理类的方法!
CGlib实现代理
使用JDK创建代理有一个限制,它只能为接口创建代理实例.这一点可以从Proxy的接口方法
newProxyInstance(ClassLoader loader,Class [] interfaces,InvocarionHandler h)中看的很清楚
第二个入参 interfaces就是需要代理实例实现的接口列表.
对于没有通过接口定义业务方法的类,如何动态创建代理实例呢? JDK动态代理技术显然已经黔驴技穷,CGLib
作为一个替代者,填补了这一空缺.
GCLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用
并顺势织入横切逻辑.
1. 创建创建CGLib代理器
1 public class CglibProxy implements MethodInterceptor { 2 3 private Enhancer enhancer = new Enhancer(); 4 //设置被代理对象 5 public Object getProxy(Class clazz){ 6 enhancer.setSuperclass(clazz); 7 enhancer.setCallback(this); 8 return enhancer.create(); 9 } 10 @Override 11 public Object intercept(Object obj, Method method, 12 Object[] objects, 13 MethodProxy methodProxy) throws Throwable { 14 System.out.println("CGLig代理之前之前"); 15 Object invoke = methodProxy.invokeSuper(obj,objects); 16 System.out.println("CGLig代理之前之后"); 17 return invoke; 18 } 19 20 }
测试
1 @Test 2 public void test2(){ 3 //TODO CGlib实现 4 CglibProxy cglibProxy = new CglibProxy(); 5 UserServiceImpl userService= (UserServiceImpl) 6 cglibProxy.getProxy(UserServiceImpl.class); 7 userService.login(); 8 }
结果:
本博客文章均已测试验证,欢迎评论、交流、点赞。
部分文章来源于网络,如有侵权请联系删除。
转载请注明原文链接:https://www.cnblogs.com/sueyyyy/p/9277160.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix