CGLIB 详解
依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
简介
CGLIB(Code Generator Library)是一个强大的、高性能的代码生成库。
其被广泛应用于AOP框架(Spring)中,用以提供方法拦截操作。
CGLIB代理主要通过对字节码的操作,以控制对象的访问。
CGLIB底层使用了ASM(一个短小精悍的字节码操作框架)来操作字节码生成新的类。
CGLIB相比于JDK动态代理更加强大:
JDK动态代理虽然简单易用,但只能对接口进行代理。
如果要代理的类为一个普通类,没有接口,那么Java动态代理就没法使用了。
Java动态代理使用Java原生的反射API进行操作(运行期),在生成类上比较高效。
CGLIB使用ASM框架直接对字节码进行操作(编译期),在类的执行过程中比较高效
Enhancer 介绍
Enhancer:
Enhancer既能够代理普通的class,也能够代理接口。
Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)。
Enhancer不能够拦截final类与方法。
Enhancer.setSuperclass(Class superclass);
用来设置父类型
Enhancer.setCallback(Callback callback);
Enhancer.setCallback(new InvocationHandler(){});
Enhancer.setCallback(new MethodInterceptor(){});
增强
Enhancer.create(Class type, Callback callback);
Enhancer.create(Class superclass, Class[] interfaces, Callback callback);
Enhancer.create(Class[] argumentTypes, Object[] arguments);
方法是用来创建代理对象,其提供了很多不同参数的方法用来匹配被增强类的不同构造方法。
Callback
Callback是一个空的接口,在Cglib中它的实现类有以下几种:
MethodInterceptor
NoOp
LazyLoader
Dispatcher
InvocationHandler
FixedValue
MethodInterceptor:
它可以实现类似于AOP编程中的环绕增强(around-advice)。
它只有一个方法:
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy)
代理类的所有方法调用都会转而执行这个接口中的intercept方法而不是原方法。
如果需要在intercept方法中执行原方法可以使用参数method进行反射调用,
或者使用参数proxy 一 proxy.invokeSuper(obj, args);
后者会快一些(反射调用比正常的方法调用的速度慢很多)。
MethodInterceptor允许我们完全控制被拦截的方法,并且提供了手段对原方法进行调用,
因为 MethodInterceptor的效率不高,它需要产生不同类型的字节码,
并且需要生成一些运行时对象(InvocationHandler就不需要),所以Cglib提供了其它的接口供我们选择。
InvocationHandler:
它的使用方式和MethodInterceptor差不多。
需要注意的一点是,所有对invoke()方法的参数proxy对象的方法调用都会被委托给同一个InvocationHandler,
所以可能会导致无限循环。
NoOp:
这个接口只是简单地把方法调用委托给了被代理类的原方法,
不做任何其它的操作。
LazyLoader,它也提供了一个方法:
Object loadObject()
loadObject()方法会在第一次被代理类的方法调用时触发,它返回一个代理类的对象,
这个对象会被存储起来然后负责所有被代理类方法的调用,一种lazy模式。
如果被代理类或者代理类的对象的创建比较麻烦,而且不确定它是否会被使用,那么可以选择使用这种lazy模式来延迟生成代理。
Dispatcher:
Dispatcher和LazyLoader接口相同,也是提供了loadObject()方法。
不过它们之间不同的地方在于,
Dispatcher的loadObject()方法在每次发生对原方法的调用时都会被调用并返回一个代理对象来调用原方法。
也就是说Dispatcher的loadObject()方法返回的对象并不会被存储起来,
可以类比成Spring中的Prototype类型,而LazyLoader则是lazy模式的Singleton。
ImmutableBean 不可变Bean
ImmutableBean允许创建一个原来对象的包装类,
这个包装类是不可变的,任何改变底层对象的包装类操作都会抛出IllegalStateException。
SampleBean bean = new SampleBean();
bean.setValue("Hello world");
SampleBean immutableBean = (SampleBean) ImmutableBean.create(bean); //创建不可变类
immutableBean.setValue("Hello cglib"); //直接修改将throw exception
bean.setValue("Hello world, again"); //可以通过底层对象来进行修改
BeanGenerator
运行时动态的创建一个bean
BeanGenerator beanGenerator = new BeanGenerator();
beanGenerator.addProperty("value",String.class);
Object myBean = beanGenerator.create();
Method setter = myBean.getClass().getMethod("setValue",String.class);
setter.invoke(myBean,"Hello cglib");
Method getter = myBean.getClass().getMethod("getValue");
BeanCopier
从一个bean复制到另一个bean中,还提供了一个转换器,用来在转换的时候对bean的属性进行操作。
BeanCopier.create(Class source, Class target, boolean useConverter)
BeanCopier copier = BeanCopier.create(Bean1.class, Bean2.class, false); //设置为true,则使用converter
Bean1 bean1 = new Bean1();
bean1.setValue("Hello cglib");
Bean2 bean2 = new Bean2();
copier.copy(bean1, bean2, null); //设置为true,则传入converter,指明怎么进行转换
BeanMap
BeanMap类实现了Java Map,将一个bean对象中的所有属性转换为一个<String,Obejct>的Java Map
BeanMap map = BeanMap.create(bean); //将对象转为BeanMap
public abstract class BeanMap implements Map {
protected Object bean;
public Object get(Object key) {
return this.get(this.bean, key);
}
public Object put(Object key, Object value) {
return this.put(this.bean, key, value);
}
public void setBean(Object bean) {
this.bean = bean;
}
public Object getBean() {
return this.bean;
}
}
参考
https://blog.csdn.net/danchu/article/details/70238002
https://blog.csdn.net/Q_AN1314/article/details/79724334
CGLIB 详解的更多相关文章
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理
Spring AOP详解 . JDK动态代理.CGLib动态代理 原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...
- JDK、CGlib动态代理详解
Java动态代理之JDK实现和CGlib实现(简单易懂) 一 JDK和CGLIB动态代理原理 1.JDK动态代理 利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生 ...
- 静态代理,动态代理,Cglib代理详解
一.静态代理 新建一个接口 定义一个玩家方法: package com."".proxy.staticc; public interface Iplayer { public vo ...
- 代理模式详解:静态代理+JDK/CGLIB 动态代理实战
1. 代理模式 代理模式是一种比较好的理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标 ...
- Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现
我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- Spring 3.x jar 包详解 与 依赖关系
以下的内容我会持续更新(当然是我有新发现的时候); 以下内容是我在网上搜索.整理.修改的而成的内容.由于很多内容都是转载了,无法追溯到源头,因此无法一一对原作者进行道谢. 这几天,我查阅大量的官方的文 ...
- Spring 3.x jar 包详解 与 依赖关系(转)
以下的内容我会持续更新(当然是我有新发现的时候); 以下内容是我在网上搜索.整理.修改的而成的内容.由于很多内容都是转载了,无法追溯到源头,因此无法一一对原作者进行道谢. 这几天,我查阅大量的官方的文 ...
随机推荐
- 【JS学习】慕课网2-7 练习题:制作新按钮,“新窗口打开网站” ,点击打开新窗口。
要求: 1.新窗口打开时弹出确认框,是否打开 提示: 使用 if 判断确认框是否点击了确定,如点击弹出输入对话框,否则没有任何操作. 2.通过输入对话框,确定打开的网址,默认为 http://www. ...
- 八、结构模式之组合(Composite)模式
组合模式属于对象的结构模式,有时又叫做部分-整体模式,组合模式将对象组织到树结构中,可以用来描述整体与部分的联系.其可以使客户端将单纯元素和组合元素同等对待. 当需求中是体现部分与整体层次的结构时,以 ...
- Python新建文件夹
import os os.mkdir('OS-Demo-2') os.makedirs('OS-Demo-3/sub-Dir-1') os.mkdir()和os.makedirs()都可以新建文件夹, ...
- SnowFlakeId 分布式雪花id算法
package com.jn.baseservice.utils; import com.jn.baseservice.common.Number; import lombok.Getter; imp ...
- fastDFS配置文件 fdfs_client.conf
# connect timeout in seconds# default value is 30sconnect_timeout=30 # network timeout in seconds# d ...
- 【NOI2019模拟2019.6.29】组合数(Lucas定理、数位dp)
Description: p<=10且p是质数,n<=7,l,r<=1e18 题解: Lucas定理: \(C_{n}^m=C_{n~mod~p}^{m~mod~p}*C_{n/p} ...
- Codeforces F. Bits And Pieces(位运算)
传送门. 位运算的比较基本的题. 考虑枚举\(i\),然后二进制位从大到小考虑, 对于第\(w\)位,如果\(a[i][w]=1\),那么对\(j.k\)并没有什么限制. 如果\(a[i][w]=0\ ...
- putty字体和颜色修改
来源:https://www.igvita.com/2008/04/14/custom-putty-color-themes/ 网站上有putty的注册表,可以修改putty显示的配色方案. 非常棒!
- DOM学习总结(二)
一.什么是DOM属性 DOM属性简单来说就是HTML的属性值 二.常见的DOM属性有哪些? 1.innerHTML 属性 获取元素的内容,想要拿到某个元素的文本内容,直接在后面加 .innerHTML ...
- BZOJ 5120: [2017国家集训队测试]无限之环(费用流)
传送门 解题思路 神仙题.调了一个晚上+半个上午..这道咋看咋都不像图论的题竟然用费用流做,将行+列为奇数的点和偶数的点分开,也就是匹配问题,然后把一个点复制四份,分别代表这个点的上下左右接头,如果有 ...