cglib invoke 和 invokeSuper 可用的组合
在深入字節(jié)碼理解invokeSuper無限循環(huán)的原因中,我們理解的cglib的原理和其中一個合理的調(diào)用方式。但是這個調(diào)用方式是基于類的,對所有實(shí)例生效。實(shí)際場景中,我們可能只是希望代理某個具體的實(shí)例,而且這個實(shí)例會有自己的特有屬性。這個時候要怎么做呢?
?
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);}} }?
通常我們會生成一個攔截器類,然后把實(shí)例傳遞進(jìn)去,調(diào)用的時候使用被代理的對象。
執(zhí)行代碼:
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調(diào)用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 }調(diào)用的時候,會先進(jìn)行類型轉(zhuǎn)換。這樣問題就來了,我們傳入的delegate是一個sampleClasss實(shí)例,而不是新生成的對象,所以類型轉(zhuǎn)換出錯。所以如果代理具體實(shí)例,正確的寫法是:
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 }?
總結(jié):
cglib動態(tài)代理
如果代理的類本身,需要使用
public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {return methodProxy.invoke(o, objects); }如果代理的是實(shí)例,需要使用
public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {return methodProxy.invoke(delegate, objects); }?
?
轉(zhuǎn)載于:https://www.cnblogs.com/yangmengdx3/p/9221806.html
總結(jié)
以上是生活随笔為你收集整理的cglib invoke 和 invokeSuper 可用的组合的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 剑指offer 面试31题
- 下一篇: Open Train 10394