1. 程式人生 > >【原創】學習CGLIB動態代理中遇到的問題

【原創】學習CGLIB動態代理中遇到的問題

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) throws
Throwable { 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動態代理中遇到的問題