cglib invoke 和 invokeSuper 可用的组合
在深入字节码理解invokeSuper无限循环的原因中,我们理解的cglib的原理和其中一个合理的调用方式。但是这个调用方式是基于类的,对所有实例生效。实际场景中,我们可能只是希望代理某个具体的实例,而且这个实例会有自己的特有属性。这个时候要怎么做呢?
public class CglibDynamicProxyDemo {static class SampleClass {public void print(){System.out.println("hello world");}}public static void main(String[] args) {SampleClass sampleClass = new SampleClass();SampleClass sample = createCglibDynamicProxy(sampleClass);sample.print();}private static SampleClass createCglibDynamicProxy(SampleClass delegate) {Enhancer enhancer = new Enhancer();enhancer.setCallback(new CglibInterceptor(delegate));enhancer.setSuperclass(SampleClass.class);return (SampleClass) enhancer.create();}private static class CglibInterceptor implements MethodInterceptor {private Object delegate;public CglibInterceptor(Object delegate) {this.delegate = delegate;}@Overridepublic Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {return methodProxy.invokeSuper(delegate, objects);}} }
通常我们会生成一个拦截器类,然后把实例传递进去,调用的时候使用被代理的对象。
执行代码:
Exception in thread "main" java.lang.ClassCastException: com.ym.materials.proxy.CglibDynamicProxyDemo$SampleClass cannot be cast to com.ym.materials.proxy.CglibDynamicProxyDemo$SampleClass$$EnhancerByCGLIB$$db74855eat com.ym.materials.proxy.CglibDynamicProxyDemo$SampleClass$$EnhancerByCGLIB$$db74855e$$FastClassByCGLIB$$6a2a8700.invoke(<generated>)at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)at com.ym.materials.proxy.CglibDynamicProxyDemo$CglibInterceptor.intercept(CglibDynamicProxyDemo.java:42)at com.ym.materials.proxy.CglibDynamicProxyDemo$SampleClass$$EnhancerByCGLIB$$db74855e.print(<generated>)at com.ym.materials.proxy.CglibDynamicProxyDemo.main(CglibDynamicProxyDemo.java:22)
异常了,why?
通过前面的分析,我们知道invokeSuper调用fci.f2.invoke(fci.i2, obj, args),使用的是第三个生成类SampleClass$$EnhancerByCGLIB$$8ed28f$$FastClassByCGLIB$$520b645b,方法签名是:CGLIB$test$0
通过方法签名的hashcode映射后得到索引为16
6 case -1659809612: 7 if(var10000.equals("CGLIB$test$0()V")) { 8 return 16; 9 } 10 break;
1 public class SampleClass$$EnhancerByCGLIB$$8ed28f$$FastClassByCGLIB$$520b645b extends FastClass { 2 3 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException { 4 8ed28f var10000 = (8ed28f)var2; 5 int var10001 = var1; 6 7 try { 8 switch(var10001) { 9 case 7: 10 var10000.test(); 11 return null; 12 case 16: 13 var10000.CGLIB$test$0(); 14 return null; 15 } catch (Throwable var4) { 16 throw new InvocationTargetException(var4); 17 } 18 19 throw new IllegalArgumentException("Cannot find matching method/constructor"); 20 } 21 }
调用的时候,会先进行类型转换。这样问题就来了,我们传入的delegate是一个sampleClasss实例,而不是新生成的对象,所以类型转换出错。所以如果代理具体实例,正确的写法是:
1 private static class CglibInterceptor implements MethodInterceptor { 2 3 private Object delegate; 4 5 public CglibInterceptor(Object delegate) { 6 this.delegate = delegate; 7 } 8 9 @Override 10 public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable { 11 return methodProxy.invoke(delegate, objects); 12 } 13 }
总结:
cglib动态代理
如果代理的类本身,需要使用
public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {return methodProxy.invoke(o, objects); }
如果代理的是实例,需要使用
public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {return methodProxy.invoke(delegate, objects); }
转载于:https://www.cnblogs.com/yangmengdx3/p/9221806.html
cglib invoke 和 invokeSuper 可用的组合相关推荐
- cglib:缺少的手册
字节码检测库cglib是许多众所周知的Java框架(例如Hibernate (现在不再 ))或Spring最受欢迎的选择,它们可以完成肮脏的工作. 字节码检测允许在Java应用程序的编译阶段之后操作或 ...
- Spring的@Configuration使用cglib代理的效果和我自己写的简单实现
下面的代码,照着复制就能跑起来 今天看了下Spring的@Configuration,即java类配置bean,(这个spring3的新功能,虽然现在已经spring5了,但是这种配置bean的方式也 ...
- CGLIB动态代理之intercept函数刨析
网上搜CGLIB动态代理,几乎所有的博文都只给了示例代码而缺少对代码的解释说明(特别是关键的intercept函数),看完实在是云里雾里.所以,这篇博文将带你从源码的角度来理解intercept函数. ...
- Spring原理学习(七)JDK动态代理与CGLIB代理底层实现
AOP 底层实现方式之一是代理,由代理结合通知和目标,提供增强功能. 除此以外,aspectj 提供了两种另外的 AOP 底层实现: 第一种是通过 ajc 编译器在编译 class 类文件时,就把通知 ...
- cglib创建代理对象(1)
cglib创建代理对象 还是从一个的小demo开始 例子 被代理的类 public class Bean{public String sayHello(String name) {return &qu ...
- 静态代理,JDK动态代理和CGLIB代理入门学习
之前面试时面试官问我:"你知道spring中有哪几种代理吗?" 啊?代理?啥子代理?VPN代理吗?嘿嘿,面试官你要种子直说啊......被刷下来了.好吧,入门学习下代理. 为什么需 ...
- 死磕cglib系列之一 cglib简介与callback解析
简介 cglib是一套java动态代理实现框架,cglib被应用到spring app,hibernate等高级业务框架,spring事务在业务实现类未实现接口的情况下也会使用该技术. 实际上,cgl ...
- Spring 面向切面编程 第4关:AOP实现原理-CgLib动态代理
目录 任务描述 相关知识 代理模式(Proxy) AOP实现的两种方式 CGLIB动态代理步骤 模拟AOP实现 代理类说明 编程要求 测试说明 参考代码 任务描述 我们知道,Spring AOP的主要 ...
- Linux 高可用(HA)集群之keepalived+lvs
一:前言 Keepalived使用的vrrp协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP);Keepalived的目的是模拟路由器的 ...
最新文章
- python mkl freebsd_FreeBSD:在uwsgi中使用python3而不是python2
- java 预览zip_java压缩包上传,解压,预览(利用editor.md和Jstree实现)和下载
- 转载:tcpdump抓包和Wireshark解包
- foobar2000转换APE参数设置
- 使用 ListView 控件展示数据
- android卡片 弹簧滑动,一种通用式弹簧卡扣的制作方法
- 计算机财务模型管理实验内容,财务分析模型实验报告
- c语言用分治法求最大最小值,C语言实现分治法实例
- 为什么程序员不应该在同一家公司待太久?
- vue PC端菜单优化(第一个菜单隐藏的时候,整个菜单都不显示)
- bzoj4564: [Haoi2016]地图 仙人掌的圆方树 莫队 分块
- 股票筛选。如何查找股票?如何查找潜力股?
- ES6 findIndex()返回结果有true,却返回的索引位置一直是-1
- Python攻防-截取屏幕并自动发送指定邮箱
- linux发展史--Linux学习笔记(一)
- “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
- Source insight 4.0 显示右边文件
- 程序媛人生——专访“龙书”《编译原理》联合作者 Monica S. Lam
- 我们分手吧,因为我不是处女!
- 双11“静悄悄”,折腾14年终于卷不动了?
热门文章
- 只有一流的人才能干出一流的工作,只有具备大量一流的人才的企业才能成为一流的企业...
- 野火STM32F103教学视频完整目录(配合霸道-指南者开发板)
- 业界谈AI赋能传统金融:精细化、数字化、个性化成三大关键词
- 微软10亿美元投资AI公司助力云计算,研发通用人工智能
- 28条有关人工智能的名言,靠不靠谱你来看!
- 重新配对_郑思维和陈清晨当年配对也很强,为什么被拆开重新和黄雅琼配对
- 原码一位乘法器设计_对原码、反码和补码的加深理解
- python 写入网络视频文件很慢_OpenCV视频写入详解_Python,视频保存0kb问题
- 003_Spring使用Slf4j和logback日志
- html怎么加载xml文档,在html中解析xml文件(javascript 读取)