zoukankan      html  css  js  c++  java
  • 【原创】学习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!
    调用真实对象后
  • 相关阅读:
    关于Maya Viewport 2.0 API 开发的介绍视频
    春节大假
    Some tips about the life cycle of Maya thread pool
    Can I compile and run Dx11Shader for Maya 2015 on my side?
    How to get current deformed vertex positions in MoBu?
    想加入全球首届的 欧特克云加速计划吗?
    三本毕业(非科班),四次阿里巴巴面试,终拿 offer(大厂面经)
    mac、window版编辑器 webstorm 2016... 永久破解方法。
    node 搭载本地代理,处理web本地开发跨域问题
    js 一维数组,转成嵌套数组
  • 原文地址:https://www.cnblogs.com/caogen1991/p/8127345.html
Copyright © 2011-2022 走看看