【原創】學習CGLIB動態代理中遇到的問題
阿新 • • 發佈:2017-12-27
tcl efi 類對象 devel ini debugging app 原創 sco
代碼清單1 CGLIB動態代理
1 package wulj.proxy.cglibProxy; 2 3 import java.lang.reflect.Method; 4 5 import net.sf.cglib.proxy.Enhancer; 6 import net.sf.cglib.proxy.MethodInterceptor; 7 import net.sf.cglib.proxy.MethodProxy; 8 9 public class CglibProxyExample implements MethodInterceptor { 10 11/** 12 * 代理邏輯方法 13 * @param proxy 代理對象 14 * @param method 方法 15 * @param args 方法參數 16 * @param methodProxy 方法代理 17 * @return 代理邏輯返回 18 * @throws Throwable 異常 19 * 20 */ 21 @Override 22 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throwsThrowable { 23 System.out.println("調用真實對象前"); 24 //CGLIB反射調用真實對象方法 25 Object result = methodProxy.invokeSuper(proxy, args); 26 System.out.println("調用真實對象後"); 27 return result; 28 } 29 30 /** 31 * 生成CGLIB代理對象 32 * @param cls Class類 33 *@return Class類的CGLIB代理對象 34 */ 35 public Object getProxy(Class<?> cls){ 36 //CGLIB enhancer 增強類對象 37 Enhancer enhancer = new Enhancer(); 38 //設置增強類型 39 enhancer.setSuperclass(cls); 40 //定義代理邏輯對象為當前對象,要求當前對象實現MethodInterceptor方法 41 enhancer.setCallback(this); 42 //生成並返回代理對象 43 return enhancer.create(); 44 45 } 46 47 }
代碼清單2 真實對象
1 package wulj.proxy; 2 3 public class ReflectServiceImpl { 4 private String name = ""; 5 public void sayHello(String name){ 6 System.out.println(name); 7 } 8 public String getName() { 9 return name; 10 } 11 public void setName(String name) { 12 this.name = name; 13 } 14 15 }
代碼清單3 測試類
1 package wulj.proxy.cglibProxy; 2 3 import wulj.reflect.ReflectServiceImpl; 4 5 public class TestCGLIbProxyMain { 6 7 public static void main(String[] args) { 8 CglibProxyExample cpe = new CglibProxyExample(); 9 ReflectServiceImpl obj = (ReflectServiceImpl) cpe.getProxy(ReflectServiceImpl.class);//獲得代理對象 10 obj.sayHello("hello,world!");//調用邏輯處理方法 11 } 12 }
原本只引入了cglib-3.2.5.jar,執行main方法時報錯如下:
Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type
at net.sf.cglib.core.TypeUtils.parseType(TypeUtils.java:184)
at net.sf.cglib.core.KeyFactory.<clinit>(KeyFactory.java:72)
at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:72)
at wulj.proxy.cglibProxy.CglibProxyExample.getProxy(CglibProxyExample.java:37)
at wulj.proxy.cglibProxy.TestCGLIbProxyMain.main(TestCGLIbProxyMain.java:9)
Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 5 more
報錯顯示有找不到的類,上網查了一下知道了很多java字節碼操作和分析的第三方類庫都引用了asm.jar文件,由於工程不是Maven管理的,無法解決依賴傳遞問題,所以要手動引入asm.jar文件。把asm.jar文件添加到項目路徑裏,運行,然後就正常了,此處參考:https://www.cnblogs.com/gl-developer/p/7115644.html
引入asm-3.3.1.jar後執行main方法是,又報下面的錯:
Exception in thread "main" java.lang.ExceptionInInitializerError
at wulj.proxy.cglibProxy.CglibProxyExample.getProxy(CglibProxyExample.java:37)
at wulj.proxy.cglibProxy.TestCGLIbProxyMain.main(TestCGLIbProxyMain.java:9)
Caused by: java.lang.IllegalStateException: Unable to load cache item
at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:79)
at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:174)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:153)
at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)
... 2 more
Caused by: java.lang.IncompatibleClassChangeError: class net.sf.cglib.core.DebuggingClassWriter has interface org.objectweb.asm.ClassVisitor as super class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at net.sf.cglib.core.DefaultGeneratorStrategy.getClassVisitor(DefaultGeneratorStrategy.java:30)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:24)
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(Unknown Source)
at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
... 9 more
參考:http://blog.csdn.net/yuanlaishinizhu/article/details/12998847,找到解決方案,原因是:cglib版本為3.0以上,org.objectweb.asm版本為3.1.0時,版本沖突,報錯java.lang.IncompatibleClassChangeError: class net.sf.cglib.core.DebuggingClassWriter has interface org.objectweb.asm.ClassVisitor as super class
使用cglib 2.2 可解決此問題,該版本中的DebuggingClassWriter的父類為ClassWriter
執行main方法:問題解決:
調用真實對象前 hello,world! 調用真實對象後
【原創】學習CGLIB動態代理中遇到的問題