【原创】学习CGLIB动态代理中遇到的问题
代码清单1 CGLIB动态代理
package wulj.proxy.cglibProxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; public class CglibProxyExample implements MethodInterceptor { /**
* 代理逻辑方法
* @param proxy 代理对象
* @param method 方法
* @param args 方法参数
* @param methodProxy 方法代理
* @return 代理逻辑返回
* @throws Throwable 异常
*
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真实对象前");
//CGLIB反射调用真实对象方法
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("调用真实对象后");
return result;
} /**
* 生成CGLIB代理对象
* @param cls Class类
* @return Class类的CGLIB代理对象
*/
public Object getProxy(Class<?> cls){
//CGLIB enhancer 增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
enhancer.setCallback(this);
//生成并返回代理对象
return enhancer.create(); } }
代码清单2 真实对象
package wulj.proxy; public class ReflectServiceImpl {
private String name = "";
public void sayHello(String name){
System.out.println(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} }
代码清单3 测试类
package wulj.proxy.cglibProxy; import wulj.reflect.ReflectServiceImpl; public class TestCGLIbProxyMain { public static void main(String[] args) {
CglibProxyExample cpe = new CglibProxyExample();
ReflectServiceImpl obj = (ReflectServiceImpl) cpe.getProxy(ReflectServiceImpl.class);//获得代理对象
obj.sayHello("hello,world!");//调用逻辑处理方法
}
}
原本只引入了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动态代理中遇到的问题的更多相关文章
- 说说cglib动态代理
前言 jdk中的动态代理通过反射类Proxy和InvocationHandler回调接口实现,要求委托类必须实现一个接口,只能对该类接口中定义的方法实现代理,这在实际编程中有一定的局限性. cglib ...
- Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)
一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...
- Java代理(静态代理、JDK动态代理、CGLIB动态代理)
Java中代理有静态代理和动态代理.静态代理的代理关系在编译时就确定了,而动态代理的代理关系是在运行期确定的.静态代理实现简单,适合于代理类较少且确定的情况,而动态代理则给我们提供了更大的灵活性. J ...
- Java代理:静态代理、JDK动态代理和CGLIB动态代理
代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式.所谓的代理者是指一个类别可以作为其它东西的接口.代理者可以作任何东西的接口:网络连接.存储器中的大对象.文件或其它昂贵或无法复制 ...
- spring框架中JDK和CGLIB动态代理区别
转载:https://blog.csdn.net/yhl_jxy/article/details/80635012 前言JDK动态代理实现原理(jdk8):https://blog.csdn.net/ ...
- Spring中的cglib动态代理
Spring中的cglib动态代理 cglib:Code Generation library, 基于ASM(java字节码操作码)的高性能代码生成包 被许多AOP框架使用 区别于JDK动态代理,cg ...
- 【Java EE 学习 51】【Spring学习第三天】【cglib动态代理】【AOP和动态代理】【切入点表达式】
一.cglib动态代理 1.简介 (1)CGlib是一个强大的,高性能,高质量的Code生成类库.它可以在运行期扩展Java类与实现Java接口. (2) 用CGlib生成代理类是目标类的子类. (3 ...
- 017 Java中的静态代理、JDK动态代理、cglib动态代理
一.静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由业务实现类.业务代理类两部分组成.业务实现类负责实现主要的业务方法,业 ...
- SSM-Spring-10:Spring中cglib动态代理
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 何为动态代理,就不扯皮了,上一篇博客刚刚提到,那cglib动态代理又怎么写,我拿个和上个例子相似的案例来写 具 ...
随机推荐
- jQuery 获取DOM节点的两种方式
jQuery中包裹后的DOM对象实际上是一个数组,要获得纯粹的DOM对象可以有两种方式: 1.使用数组索引方式访问,例如: var dom = $(dom)[0]; 如: $("#id&qu ...
- MongoDB笔记(三):Document 数据插入、删除、更新
实例数据库caliven.集合users 一.插入文档 1.插入文档 db.[documentName].insert({}) 2.批量插入文档 .shell 这样执行是错误的db.[document ...
- Python MySQLdb 使用utf-8 编码插入中文数据
参考地址:http://blog.csdn.net/dkman803/article/details/1925326/ 本人在使用python,mysqldb操作数据库的时候,发现如下问题,编码如下: ...
- 监听器如何获取Spring配置文件
我们在做项目的时候,会用到监听器去获取spring的配置文件,然后从中拿出我们需要的bean出来,比如做网站首页,假设商品的后台业务逻辑都做好了,我们需要创建一个监听器,在项目启动时将首页的数据查询出 ...
- [原创]如何让freeswitch转发客户端自定义的INFO消息
如何让freeswitch转发客户端自定义的INFO消息 英文概述: this article is about how to configure freeswitch to forward self ...
- 树莓派学习笔记——apt方式安装opencv
0.前言 本文介绍怎样在树莓派中通过apt方式安装opencv.并通过一个简单的样例说明怎样使用opencv. 相比于源码方式安装opencv,通过apt方式安装过程步骤简单些,消耗的时间也少 ...
- eclipse 建立maven项目 显示红叉的解决方法
1.建立好之后就会发现项目有红叉. 这时发现查查在main处,打开项目>属性>Java Build Path>source,发现里边有红叉(如下图),这是由于我们的src/main下 ...
- linux用户密码生成
linux账户保存在/etc/passwd,密码保存在/etc/shadow. 通过man 5 passwd,man 5 shadow可查看文件中各字段含义. encrypted password ...
- 【转】【Mac系统】之ADB命令总结
参考文章: 张明云:<Android ADB命令大全(通过ADB命令查看wifi密码.MAC地址.设备信息.操作文件.查看文件.日志信息.卸载.启动和安装APK等)> Yjnull:< ...
- visualvm远程监控jvm两种配置方法
参考:http://blog.itpub.net/17203031/viewspace-765810 一.Jstatd RMI远程监控方法 VisualVM在监控本地JVM的时候是很方便的.只要应用程 ...