Cglib动态代理实现原理--源码解读
Cglib动态代理实现⽅式
我们先通过⼀个demo看⼀下Cglib是如何实现动态代理的。
⾸先定义个服务类,有两个⽅法并且其中⼀个⽅法⽤final来修饰。
public class PersonService {
public PersonService() {
System.out.println("PersonService构造");
}
//该⽅法不能被⼦类覆盖
final public Person getPerson(String code) {
System.out.println("PersonService:getPerson>>"+code);
return null;
}
public void tPerson() {
System.out.println("PersonService:tPerson");
}
}
Cglib是⽆法代理final修饰的⽅法的,具体原因我们⼀会通过源码来分析。
然后,定义⼀个⾃定义MethodInterceptor。
public class CglibProxyIntercepter implements MethodInterceptor {
@Override
public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("执⾏前...");
Object object = methodProxy.invokeSuper(sub, objects);
System.out.println("执⾏后...");
return object;
}
}
我们看⼀下intercept⽅法⼊参,sub:cglib⽣成的代理对象,method:被代理对象⽅法,objects:⽅法⼊参,methodProxy:代理⽅法最后,我们写个例⼦调⽤⼀下,并将Cglib⽣成的代理类class⽂件输出磁盘⽅便我们反编译查看源码。
public class Test {
public static void main(String[] args) {
//代理类class⽂件存⼊本地磁盘
System.tProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
Enhancer enhancer = new Enhancer();
enhancer.tSuperclass(PersonService.class);
enhancer.tCallback(new CglibProxyIntercepter());
PersonService proxy= (PersonService) ate();
proxy.tPerson();
} }
我们执⾏⼀下会发现getPerson因为加final修饰并没有被代理,下⾯我们通过源码分析⼀下。
执⾏前...
PersonService:tPerson
执⾏后...
PersonService:getPerson>>1
⽣成代理类
团员自我评议
执⾏Test测试类可以得到Cglib⽣成的class⽂件,⼀共有三个class⽂件我们反编译以后逐个说⼀下他们的作⽤。动态图片gif
PersonService$$EnhancerByCGLIB$$eaaaed75就是cglib⽣成的代理类,它继承了PersonService类。
public class PersonService$$EnhancerByCGLIB$$eaaaed75
extends PersonService
implements Factory
{
private boolean CGLIB$BOUND;女的性欲强
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;//拦截器
private static final Method CGLIB$tPerson$0$Method;//被代理⽅法每日一句英语
private static final MethodProxy CGLIB$tPerson$0$Proxy;//代理⽅法
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$finalize$1$Method;
private static final MethodProxy CGLIB$finalize$1$Proxy;
private static final Method CGLIB$equals$2$Method;
private static final MethodProxy CGLIB$equals$2$Proxy;
private static final Method CGLIB$toString$3$Method;
private static final MethodProxy CGLIB$toString$3$Proxy;
private static final Method CGLIB$hashCode$4$Method;
private static final MethodProxy CGLIB$hashCode$4$Proxy;
private static final Method CGLIB$clone$5$Method;
private static final MethodProxy CGLIB$clone$5$Proxy;
static void CGLIB$STATICHOOK1()
{
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
税收学专业Class localClass1 = Class.forName("com.lib.PersonService$$EnhancerByCGLIB$$eaaaed75");//代理类
Class localClass2;//被代理类PersionService
父亲节几月几号
Method[] tmp95_92 = ReflectUtils.findMethods(new String[] { "finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (localClass2 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$finalize$1$Method = tmp95_92[0];
CGLIB$finalize$1$Proxy = ate(localClass2, localClass1, "()V", "finalize", "CGLIB$finalize$1");
Method[] tmp115_95 = tmp95_92;
CGLIB$equals$2$Method = tmp115_95[1];
CGLIB$equals$2$Proxy = ate(localClass2, localClass1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
Method[] tmp135_115 = tmp115_95;
CGLIB$toString$3$Method = tmp135_115[2];
体操口号CGLIB$toString$3$Proxy = ate(localClass2, localClass1, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
Method[] tmp155_135 = tmp135_115;
CGLIB$hashCode$4$Method = tmp155_135[3];
CGLIB$hashCode$4$Proxy = ate(localClass2, localClass1, "()I", "hashCode", "CGLIB$hashCode$4");
Method[] tmp175_155 = tmp155_135;
CGLIB$clone$5$Method = tmp175_155[4];
CGLIB$clone$5$Proxy = ate(localClass2, localClass1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
tmp175_155;
Method[] tmp223_220 = ReflectUtils.findMethods(new String[] { "tPerson", "()V" }, (localClass2 =
Class.forName("com.lib.PersonService")).getDeclaredMethods());
CGLIB$tPerson$0$Method = tmp223_220[0];
CGLIB$tPerson$0$Proxy = ate(localClass2, localClass1, "()V", "tPerson", "CG
LIB$tPerson$0");
tmp223_220;
return;
}
我们通过代理类的源码可以看到,代理类会获得所有在⽗类继承来的⽅法,并且会有MethodProxy与之对应,⽐如 Method CGLIB$tPerson$0$Method、MethodProxy CGLIB$tPerson$0$Proxy;
⽅法的调⽤
//代理⽅法(methodProxy.invokeSuper会调⽤)
final void CGLIB$tPerson$0() {
super.tPerson();
}
//被代理⽅法(methodProxy.invoke会调⽤,这就是为什么在拦截器中调⽤methodProxy.invoke会死循环,⼀直在调⽤拦截器)
public final void tPerson() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
//调⽤拦截器
var10000.intercept(this, CGLIB$tPerson$0$Method, CGLIB$emptyArgs, CGLIB$tPerson$0$Proxy);
} el {
super.tPerson();
}
}
调⽤过程:代理对象调⽤this.tPerson⽅法->调⽤拦截器->methodProxy.invokeSuper->CGLIB$tPerson$0->被代理对象tPerson⽅法
MethodProxy
拦截器MethodInterceptor中就是由MethodProxy的invokeSuper⽅法调⽤代理⽅法的,MethodProxy⾮常关键,我们分析⼀下它具体做了什么。
创建MethodProxy
public class MethodProxy {
private Signature sig1;
private Signature sig2;
private MethodProxy.CreateInfo createInfo;
private final Object initLock = new Object();
private volatile MethodProxy.FastClassInfo fastClassInfo;
//c1:被代理对象Class
//c2:代理对象Class
//desc:⼊参类型
/
/name1:被代理⽅法名
//name2:代理⽅法名
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
MethodProxy proxy = new MethodProxy();
proxy.sig1 = new Signature(name1, desc);//被代理⽅法签名
proxy.sig2 = new Signature(name2, desc);//代理⽅法签名
return proxy;
}
private static class CreateInfo {
Class c1;
Class c2;
NamingPolicy namingPolicy;
GeneratorStrategy strategy;
boolean attemptLoad;
烧麦的包法public CreateInfo(Class c1, Class c2) {
this.c1 = c1;
this.c2 = c2;
AbstractClassGenerator fromEnhancer = Current();
if(fromEnhancer != null) {
this.namingPolicy = NamingPolicy();
this.strategy = Strategy();
this.attemptLoad = AttemptLoad();
}
}
}
invokeSuper调⽤
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
this.init();
MethodProxy.FastClassInfo fci = this.fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException var4) {
TargetException();
}
}
private static class FastClassInfo {
FastClass f1;//被代理类FastClass
FastClass f2;//代理类FastClass
int i1; //被代理类的⽅法签名(index)
int i2;//代理类的⽅法签名
private FastClassInfo() {
}
}
上⾯代码调⽤过程就是获取到代理类对应的FastClass,并执⾏了代理⽅法。还记得之前⽣成三个class⽂件
吗?PersonService$$EnhancerByCGLIB$$eaaaed75$$FastClassByCGLIB$$355cb7ea.class就是代理类的FastClass,PersonService$$FastClassByCGLIB$$a076b035.class就是被代理类的FastClass。
FastClass机制