原创学习CGLIB动态代理中遇到的问题
Posted caogen1991
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创学习CGLIB动态代理中遇到的问题相关的知识,希望对你有一定的参考价值。
代码清单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动态代理中遇到的问题的主要内容,如果未能解决你的问题,请参考以下文章
jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)