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 包详解 与 依赖关系(转)
以下的内容我会持续更新(当然是我有新发现的时候); 以下内容是我在网上搜索.整理.修改的而成的内容.由于很多内容都是转载了,无法追溯到源头,因此无法一一对原作者进行道谢. 这几天,我查阅大量的官方的文 ...
随机推荐
- 华视身份证读卡器获取uid号vue单文件组件版本
<template> <div id="app" ref="app"> <object ref="CertCtl&quo ...
- React 使用antd 清空表单
handleResetClick = e => { this.props.form.resetFields();};
- web框架express学习一
服务端 node app.jsapp.jslet express = require("express"); let http = require("http" ...
- SpringBoot - @ControllerAdvice 处理异常
在Spring 3.2中,新增了@ControllerAdvice.@RestControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@Mode ...
- Java学习之DOS基础
Dos命令行dir:列出当前目录下的文件和文件夹md :创建目录rd :删除目录cd :进入指定目录cd..:退回到上一级目录cd/:退回到根目录del:删除文件exit:退出dos命令行 进入dos ...
- shell cat 合并文件,合并数据库sql文件
> 覆盖写入 >> append模式写入 ###################################################################合并数 ...
- TLS/SSL 协议 - ClientHello
ClientHello 在一次新的握手流程中,ClientHello消息总是第一条消息.这条消息将客户端的功能和首选项传送给服务器.客户端会在新建连接后,希望重新协商或者响应服务器发起的重新协商请求( ...
- 20140808 const和define区别 内联函数(inline) 栈和堆的地址分配 栈帧
1.const和define区别 const有数据类型(不能改变的变量),define只是简单的字符串替换,没有数据类型. C++程序用const完全取代 define. const还可以类成员函数为 ...
- 调用API接口,查询手机号码归属地(2)
使用pymysql pip install pymysql 创建mysql测试表 CREATE TABLE `userinfo` ( `id` int(20) NOT NULL AUTO_INCREM ...
- 面试总结【css篇】- css选择器以及优先级
优先(优先级为): !important > 内联样式 > #id > .class > tag > * > 继承 > 默认 . 当选择器的权重相同时,它将 ...