[编织消息框架][JAVA核心技术]cglib动态代理
先在mavne项目里添加cglib库
maven仓库搜索cglib版本
maven地址:http://mvnrepository.com/



点击最新的版本 3.2.5
复制到pom.xml dependencies 标签下
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
接着在TestProxy.class添加方法
public static void testCglib() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
});
UserService impTarget = (UserService) enhancer.create();
run("cglib",impTarget);
}
public static void main(String[] args) {
testNative();
testJdk();
testCglib();
}
继续运行测试:
native: 177 native: 191 native: 132 native: 179 native: 132 native: 152 native: 183 native: 131 native: 133 native: 132 native: 131 native: 133 native: 132 native: 132 native: 133
jdk: 218 jdk: 172 jdk: 172 jdk: 173 jdk: 172 jdk: 172 jdk: 172 jdk: 172 jdk: 173 jdk: 172 jdk: 174 jdk: 172 jdk: 172 jdk: 172 jdk: 173
cglib: 294 cglib: 271 cglib: 271 cglib: 284 cglib: 270 cglib: 270 cglib: 268 cglib: 268 cglib: 269 cglib: 268 cglib: 269 cglib: 269 cglib: 280 cglib: 268 cglib: 273
可以看出 cglib比jdk还要慢
我们来查看下生成的class指令有多少条
先加一行System.in.read(); 防止程序退出
public static void main(String[] args) throws IOException {
testNative();
testJdk();
testCglib();
System.in.read();
}
运行HSDB工具
1)、打开cmd窗口,运行命令:java -classpath "%JAVA_HOME%/lib/sa-jdi.jar" sun.jvm.hotspot.HSDB
2)、点击file菜单下第一项
弹出
3)、打开任务管理器,在任务管理器菜单查看->选择列->勾选PID
找到当前运行java程序的进程号pid,输入到上图的文本框中,点击ok弹出

4)、点击工具(tools)菜单下的第一项Class Browser。弹出

5)、输入包名TestProxy回车.只要看cglib生成的动态类


只要看 super class 实现类
6)、点击Create .class File,在HSDB工具运行目录下下生产cglib动态代理类


用jd-gui打开
逻辑跟JDK差不多,只要不同部分
public final String getName(int paramInt)
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null) {
return (String)tmp17_14.intercept(this, CGLIB$getName$0$Method, new Object[] { new Integer(paramInt) }, CGLIB$getName$0$Proxy);
}
return super.getName(paramInt);
}
CGLIB$CALLBACK_0 是cglib MethodInterceptor 对象
由于jd-gui无法完全反编译 看不到CGLIB$getName$0$Proxy MethodProxy 对象是如何生成的
我们用javap 看下 getName 生成多少条指令大概知道为什么会慢
javap -v TestProxy$UserServiceImpl$$EnhancerByCGLIB$$aa69a57.class > d.txt
public final java.lang.String getName(int);
descriptor: (I)Ljava/lang/String;
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=9, locals=2, args_size=2
0: aload_0
1: getfield #40 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodInterceptor;
4: dup
5: ifnonnull 17
8: pop
9: aload_0
10: invokestatic #44 // Method CGLIB$BIND_CALLBACKS:(Ljava/lang/Object;)V
13: aload_0
14: getfield #40 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodInterceptor;
17: dup
18: ifnull 53
21: aload_0
22: getstatic #46 // Field CGLIB$getName$0$Method:Ljava/lang/reflect/Method;
25: iconst_1
26: anewarray #48 // class java/lang/Object
29: dup
30: iconst_0
31: iload_1
32: new #50 // class java/lang/Integer
35: dup_x1
36: swap
37: invokespecial #53 // Method java/lang/Integer."<init>":(I)V
40: aastore
41: getstatic #55 // Field CGLIB$getName$0$Proxy:Lnet/sf/cglib/proxy/MethodProxy;
44: invokeinterface #61, 5 // InterfaceMethod net/sf/cglib/proxy/MethodInterceptor.intercept:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;
49: checkcast #63 // class java/lang/String
52: areturn
53: aload_0
54: iload_1
55: invokespecial #38 // Method com/eyu/onequeue/TestProxy$UserServiceImpl.getName:(I)Ljava/lang/String;
58: areturn
从数量上看比jdk生成的指令差不多有二倍多,慢是必然的,但cglib比jdk1.6快,原因是jdk1.6生成差不多有上百代指令
顺便说下spring 代理有两种模式 1.cglib 2.jdk
proxyTargetClass 属性,设置为true,则使用CGLIB代理,此属性默认为false,使用JDK动态代理
<aop:scoped-proxy proxy-target-class="true" />
[编织消息框架][JAVA核心技术]cglib动态代理的更多相关文章
- [编织消息框架][JAVA核心技术]jdk动态代理
需要用到的工具 jdk : javac javap class 反编译 :JD-GUI http://jd.benow.ca/ import java.lang.reflect.Invocation ...
- [编织消息框架][JAVA核心技术]动态代理介绍
由于java是种强类型静态语言,在执行时无法动态生成代码,静态语言基本都有这特性 动态生成代码有几种好处,也是弱类型语言的优点 1.部份逻辑可以实现热更新 2.远程调用实现非常适合 3.能动态生成扩展 ...
- [编织消息框架][JAVA核心技术]动态代理应用12-总结
动态代理这篇比较长,是框架组成的重要基础 回顾下学到的应用技术 1.异常应用 2.annotation技术 3.数值与逻辑分享 4.jdk.cglib.javassist等动态代理技术 5.懒处理.预 ...
- [编织消息框架][JAVA核心技术]异常应用
QException是项目业务异常基类 按模块划分子类异常,方便定位那块出错 有个来源码属性code作用定位某个功能处理出错逻辑,数字类型节省内存空间,同时减少创建子类的子类 QSocketExcep ...
- [编织消息框架][JAVA核心技术]annotation基础
应用动态代理技术要先掌握annotation技术 注解是JDK1.5之后才有的新特性,JDK1.5之后内部提供的三个注解 @Deprecated 意思是“废弃的,过时的” @Override 意思是“ ...
- [编织消息框架][JAVA核心技术]动态代理应用4
基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...
- [编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现
private static Map<Short, Map<Byte, Method>> RECEIVE_METHOD_INFO = new HashMap<>() ...
- [编织消息框架][JAVA核心技术]动态代理应用7-IRpcSend实现
根据设计生成两个接口,IRpcSend send方法返回数据要求包装成QResult对象 public interface IRpcSend { public <T> QResult< ...
- [编织消息框架][JAVA核心技术]动态代理应用4-annotationProcessor
基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...
随机推荐
- 高可用的Spring FTP上传下载工具类(已解决上传过程常见问题)
前言 最近在项目中需要和ftp服务器进行交互,在网上找了一下关于ftp上传下载的工具类,大致有两种. 第一种是单例模式的类. 第二种是另外定义一个Service,直接通过Service来实现ftp的上 ...
- ES6模块化
关于ES6模块化 历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来.其他语言都有这项功能,比如 Ruby 的require ...
- 关于网页授权的两种scope的区别说明
关于网页授权的两种scope的区别说明 1.以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的.用户感知的就是直接进入了回 ...
- php IP转换整形(ip2long)
如何将四个字段以点分开的IP网络址协议地址转换成整数呢?PHP里有这么一个函数ip2long.比如 <?php echo ip2long("10.2.1.3"); ?> ...
- 项目实战8—tomcat企业级Web应用服务器配置与会话保持
tomcat企业级Web应用服务器配置与实战 环境背景:公司业务经过长期发展,有了很大突破,已经实现盈利,现公司要求加强技术架构应用功能和安全性以及开始向企业应用.移动APP等领域延伸,此时原来开发w ...
- Jarvis OJ - [XMAN]level0 - Writeup
差不多最简单的pwn了吧,不过本菜鸟还是要发出来镇楼 分析一下,checksec 查看程序的各种保护机制 没有金丝雀,没有pie 执行时输出Hello,World,在进行输入,溢出嘛 开工 丢到id ...
- ubuntu更换开机动画
ubuntu更换启动动画 作为一个个用linux作为桌面环境,并且完全替代了windows的来说,怎么折腾好看,是一个重要的问题,而Ubuntu的开机动画,那紫色的画面,ubuntu那几个大字,实在丑 ...
- Swift开发教程--使用Storyboard进行界面跳转
使用storyboard结合代码来做确实能够给开发带来非常多的便利. 在实践的过程中,我们常常会遇到界面的跳转问题. 通过控件和界面的建立的"连接"就能够了. 假设是navigat ...
- 四、Spring Boot 多数据源 自动切换
实现案例场景: 某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库.为了在开发中以最简单的方法使用,本文基于注解 ...
- Django的信号机制
Django提供一种信号机制.其实就是观察者模式,又叫发布-订阅(Publish/Subscribe) .当发生一些动作的时候,发出信号,然后监听了这个信号的callback函数就会执行. Djang ...