• 【原创】学习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!
    调用真实对象后
  • 相关阅读:
    C# json提取多层嵌套到数组-- C# json 数组
    JS中的prototype
    JS_&&||
    js 匿名函数 js-函数定义方法
    js匿名函数确实是个好东西
    JavaScript:undefined!=false之解 及==比较的规则
    Sql 中常用日期转换Convert(Datetime) convert datetime
    jquery设置元素的readonly和disabled
    eWebEditor复制粘贴图片时过滤域名
    java构造函数使用方法总结
  • 原文地址:https://www.cnblogs.com/caogen1991/p/8127345.html
Copyright © 2020-2023  润新知