SpringAop之Cglib代理使用及源码深度解析
摘要
- Cglib 使用ASM框架生成代理类字节码问题,相对于生成字节码性能低,利用缓存解决,FastClass在方法索引查找调用很快,通过Super方式,非反射调用。
使用演示
模拟使用乘车服务类
public class TaixService {
public boolean checkOnTaix(String name){
System.out.println("乘客:"+name+"已上车");
return true;
}
void checkDownTaix(){
System.out.println("检测乘客已下车");
}
}
添加乘车服务代理,使用其中一个回调接口极其
- MethodInterceptor 实现该接口,重写intercept()方法
- InvocationHandler 实现该接口,注意是Cglib包下的。重写invoke()方法
- Callback接口很多子接口都可以实现,注意每个接口回调方式不同。
public class TaixProxy implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("欢迎选乘服务");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("下次欢迎光临");
return result;
}
}
使用
public static void main(String[] args) {
//初始化增强器
Enhancer enhancer=new Enhancer();
//设置回调接口 带入代理类
enhancer.setCallback(new TaixProxy());
//设置目标类
enhancer.setSuperclass(TaixService.class);
//创建增强
TaixService proxy=(TaixService)enhancer.create();
//开始调用
proxy.checkOnTaix("小虎");
proxy.checkDownTaix();
}
主要代理类字节码解析
1. 查看Cglib利用ASM生成代理类class
-Dcglib.debugLocation=/保存位置
在Main启动设置VM参数
2. 跟进create()—> createHelper()
private Object createHelper() {
//校验
preValidate();
//设置Key 传入一些设置目标类setSuperclass()useFactory 是否使用缓存
//该key 下一步回去缓存Map查找是否已经生成过代理字节码,没有再去生成。
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
3. AbstractClassGenerator#create()
protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
//接上面生成Key 查询Map