CGLib与JDK的动态代理
一、CGLib 简单介绍
CGLib (Code Generation Library) 是一个强大的,高性能,高质量的Code生成类库。
它能够在执行期扩展Java类与实现Java接口。
Hibernate用它来实现PO字节码的动态生成。CGLib比 Java 的 java.lang.reflect.Proxy 类更强的在于它不仅能够接管接口类的方法。还能够接管普通类的方法。
CGLib 的底层是Java字节码操作框架 —— ASM。
CGLib就是封装了ASM,简化了ASM的操作,实现了在执行期动态生成新的class。ASM是直接生成class类的方式。不会有性能问题(相对来说)
二、JDK的动态代理 (VS) CGLib
1、实现原理
JDK的动态代理——依据java的反射机制动态生成
利用反射。获取托付类的类载入器。托付类的全部接口,实例化代理类。
通过反射类Proxy以及InvationHandler回调接口实现的。可是动态代理类仅仅能对该类所实现的接口中的方法进行代理。
具有一定的局限性,而且反射的效率也不是非常高。
Proxy 毕竟是通过反射实现的,必须在效率上付出代价:有实验数据表明,调用反射比一般的函数开销至少要大 10 倍。
从程序实现上能够看出,对 proxyclass 的全部方法调用都要通过使用反射的 invoke 方法。
因此。对于性能关键的应用。使用 proxy class是须要精心考虑的。以避免反射成为整个应用的瓶颈。
CGLib ——利用ASM生成字节码原理。利用增强类,创建代理类
CGLib底层採用ASM字节码生成框架。使用字节码技术生成代理类。比反射效率要高。
可是须要主要注意的,CGLib不能对声明为final的方法进行代理。
由于CGLib原理是动态的生成被代理类的子类。
ASM可以通过改造既有类,直接生成须要的代码。
增强的代码是硬编码在新生成的类文件内部的,没有反射带来性能上的付出。它是一个普通的 Java 类而不是 proxy类,甚至可以在应用程序的类框架中拥有自己的位置,派生自己的子类。
在调用目标方法的时候,CGLib会回调MethodInterceptor接口方法拦截。来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口
2、代码实现
JDK动态代理
package DynamicProxy2upgrade; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* @ClassName: DynamicProxy
* @Description: 动态代理类。在这里做了一个升级。把代理绑定真实类的关系。Proxy生成实例的代码移到了动态代理这里
* @author 张薄- huaxiangniaoyu0109@126.com
* @date 2015年5月29日 下午9:21:19
*/
public class DynamicProxy implements InvocationHandler { private Object obj ; //托付类,真实类 DynamicProxy(Object obj){
this.obj=obj;
} //绑定代理与托付类。生成新的代理类
public Object bindProxy(Object obj){ //返回一个指定接口的代理类实例,该接口能够将方法调用指派到指定的调用处理程序,如ProxyHandler
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(obj, args); //普通的java反射代码,通过反射运行某个类的方法(invoke方法内部实现预处理,对托付类方法调用,事后处理等逻辑。)
} }
JDK动态代理执行结果:‘
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Fvemhhbmd5aW5nZmVpMDEwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
CGLib动态代理
package CGLibDynamicProxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; //一个字节码增强类,它能够方便的对你想要处理的类进行扩展
import net.sf.cglib.proxy.MethodInterceptor; //方法拦截器
import net.sf.cglib.proxy.MethodProxy; //代理类。JDK的java.long.reflect.Method类的代理类,能够方便的实现对源对象方法的调用(如invokeSuper)
/**
* @ClassName: DynamicProxybyCGLib
* @Description: 基于CGLib的动态代理
* @author 张薄- huaxiangniaoyu0109@126.com
* @date 2015年5月31日 上午8:44:19
*/
public class DynamicProxybyCGLib implements MethodInterceptor { private Object obj; //托付类
public Object getInstance(Object obj){
this.obj = obj;
Enhancer enhancer = new Enhancer(); //增强类
//不同于JDK的动态代理。它不能在创建代理时传obj对 象,obj对象必须被CGLIB包来创建
enhancer.setSuperclass(this.obj.getClass()); //设置被代理类字节码(obj将被代理类设置成父类;作为产生的代理的父类传进来的)。CGLIB依据字节码生成被代理类的子类
enhancer.setCallback(this); //设置回调函数,即一个方法拦截
return enhancer.create(); //创建代理类
} @Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("obj:" + obj.getClass().getName()); //由CGLib动态生成的代理类实例
System.out.println("method:" + method.getName()); //上文中实体类所调用的被代理的方法引用
System.out.println("methodProxy:" + methodProxy.getClass().getName()); //生成的代理类对方法的代理引用
System.out.println("args:"+ args); //參数值列表 Object object = methodProxy.invokeSuper(obj, args); //调用代理类实例上的methodProxy方法的父类方法(即实体类RealSubject中的相应方法) return object;
} }
CGLib动态代理执行结果:
三、小结
CGLib实现的原理,非常详细的原理可能我还是不太懂。可是,大概知道一个过程,首先依据Enhancer创建代理类,怎样创建的呢?依据方法setSuperclass将被代理类作为父类引入。再依据CGLib生成被代理类的子类。依据方法setCallback,回调函数(这里我们的动态代理类实现MethodInterceptor拦截器,依据拦截器的方法intercept,调用代理类的父类方法。实现了代理被代理类的方法的目的),实现方法拦截。最后用create方法创建代理类。
既然口述了CGLib的实现原理,那就再来说说JDK的动态代理吧。依据Proxy的方法newProxyInstance方法创建代理类。该方法里面的參数,分别获取了被代理类的类载入器(用于动态载入),被代理类的全部接口类(以便于实现接口类的全部方法),再通过动态代理类实现InvationHandler。实现接口方法invoke。回调函数(通过反射运行被代理类的方法),这样在实例化动态代理类的时候,就真正的创建了动态代理。
啰里啰嗦的说了这么多,收获还是有的。说出我的心得,假设大家有不同的想法,欢迎拍砖哈。
比方,CGLib的动态代理类。原理是继承,生成了被代理类的子类;而JDK的动态代理类。原理是反射,生成的代理类。实际不具备被代理类内部的方法,每一次调用都须要利用反射。调用被代理类的方法;再来看静态代理,代理类就是通过调用被代理类的方法进行执行的,而它自己本身并不详细被代理类的方法,JDK的动态代理的进步在于。利用反射,将类的载入延迟到程序执行中,解耦了代理类与被代理的关系。
CGLib与JDK的动态代理的更多相关文章
- CGLIB 和 JDK生成动态代理类的区别(转)
文章转自http://luyuanliang.iteye.com/blog/1137292 AOP 使用的设计模式就是代理模式,是对IOC设计的补充.为了扩展性,往往会加上反射,动态生成字节码,生成代 ...
- JDK 原生动态代理是怎么实现的 + 面试题
JDK 原生动态代理是怎么实现的 + 面试题 反射 反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect)的能力.简单来说就是通过反射,可以在运行期间获取.检测和调 ...
- 动态代理:JDK原生动态代理(Java Proxy)和CGLIB动态代理原理+附静态态代理
本文只是对原文的梳理总结,以及自行理解.自己总结的比较简单,而且不深入,不如直接看原文.不过自己梳理一遍更有助于理解. 详细可参考原文:http://www.cnblogs.com/Carpenter ...
- JAVA JDK的动态代理反射实现
动态代理类使用到了一个接口InvocationHandler和一个代理类Proxy ,这两个类配合使用实现了动态代理的功能. 什么是动态代理呢? 普通代理类是指: 给每个具体类写一个代理类,以后要使 ...
- 基于 JDK 的动态代理机制
『动态代理』其实源于设计模式中的代理模式,而代理模式就是使用代理对象完成用户请求,屏蔽用户对真实对象的访问. 举个最简单的例子,比如我们想要「FQ」访问国外网站,因为我们并没有墙掉所有国外的 IP,所 ...
- JDK的动态代理深入解析(Proxy,InvocationHandler)(转)
JDK的动态代理深入解析(Proxy,InvocationHandler)(转) 一.什么是动态代理 动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实.代理一般会实现它所表示的实际对象的 ...
- jdk的动态代理
至于jdk的动态代理怎么用此处并不多说,现在是更深一步的理解,jdk的Proxy类到底做了什么. Proxy.newProxyInstance可以生成代理类,此方法有三个参数(ClassLoader ...
- JDK的动态代理-----为接口进行代理
JDK的动态代理是必须掌握的,动态代理的好处就不用我多说了吧 :) 小弟最近在研究mybatis的源码实现,就开始了解mybatis的Mapper代理机制,为什么接口不用实现类也能代理? 好了,废话不 ...
- JDK的动态代理机制
JDK Proxy OverView jdk的动态代理是基于接口的,必须实现了某一个或多个随意接口才干够被代理,并且仅仅有这些接口中的方法会被代理.看了一下jdk带的动态代理api.发现没有样例实在是 ...
随机推荐
- ledisDB底层实现——本质上就是用leveldb这样的底层存储,和ssdb一样,meta里存的是hash、list等的元数据
Hash hash可以算是一种两级kv,首先通过key找到一个hash对象,然后再通过field找到或者设置相应的值. 在ledisdb里面,我们需要将key跟field关联成一个key,用来存放或者 ...
- 【BZOJ 1598】 牛跑步
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1598 [算法] A*求k短路 [代码] #include<bits/stdc+ ...
- tarjan用法——割点
今天洛谷疯狂给我推送tarjan的题(它好像发现了我最近学tarjan),我正好做一做试一试(顺便练一练快读和宏定义). 其实找割点的tarjan和算强连通分量的tarjan不一样,找割点的判定条件比 ...
- SiteMesh3使用实例和详解
一.SiteMesh介绍 SiteMesh是一个网页布局和修饰的框架,利用它可以将网页的内容和页面结构分离,以达到页面结构共享的目的.[来自百度百科] 通俗的理解就是,SiteMesh把页面中变化的和 ...
- Python 33(2)进程理论
一:什么是进程 进程指的是一个正在进行 / 运行的程序,进程是用来描述程序执行过程的虚拟概念 进程vs程序 程序:一堆代码 进程:程序的执行的过程 进程的概念起源于操作系统,进程是操作 ...
- Blender之UILayout
目标 [x] 总结Blender面板布局 总结 Blender面板中界面组件是通过UILayout进行组织的. 其主要属性如下: row() 定义横向子布局. column() 定义竖向子布局. sp ...
- Zeppelin0.6.2+sparkR2.0.2环境搭建
0.序 先吐槽一下网上旧版本的Zeppelin和R的安装,让我折腾了几个小时. 不过最终还是调通了也不容易,其实我现在一点R都没有学呢,只是刚看了一节课,但是这个工具既然出现在了Spark中,我想它还 ...
- Spring Boot (22) Spring Security
除了使用拦截器.过滤器实现对没有权限访问的页面跳转到登陆页外,还可以通过框架实现:Spring Security. 使用Spring Security 完成登陆验证: 1.pom.xml添加依赖 &l ...
- 【HTTP】长连接和短连接
1. HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问 ...
- 我和CSDN的那些事
作者:朱金灿 来源:http://blog.csdn.net/clever101 前些日子收到这样一个邀请: CSDN的工作人员还来电给我确认是否能参加.开始我有点犹豫,毕竟是在工作日的晚上,毕竟离我 ...