Cglib动态代理
具体类对象
package cn.huangwei.classLoader.Proxy; public class CglibService { public CglibService(){ System.out.println("CglibService构造器"); } public void getCglib(){ System.out.println("CglibService的get方法"); } } |
拦截器对象
package cn.huangwei.classLoader.Proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibIntercepter implements MethodInterceptor{ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // TODO Auto-generated method stub System.out.println("执行前。。。。"); Object object = proxy.invokeSuper(obj, args); System.out.println("执行后。。。。"); return object; } }
|
测试类
package cn.huangwei.classLoader.Proxy; import net.sf.cglib.proxy.Enhancer; public class TestCglibProxy { public static void main(String[] args) { //实例化增强器,类生成器 Enhancer eh = new Enhancer(); //设置目标类 eh.setSuperclass(CglibService.class); //设置拦截对象 CglibIntercepter ci = new CglibIntercepter(); eh.setCallback(ci); //生成代理类对象,返回实例 CglibService cs = (CglibService) eh.create(); cs.getCglib(); } }
|
可以得到Cglib生成的三个文件
第一个是代理类的fastclass,第二个是被代理类CglibService的fastclass
Aaaed75.class就是cglib生成的代理类,继承了CglibService类(CglibService类)实现了Factory,只给出部分关键代码
public class CglibService$$EnhancerByCGLIB$$eaaaed75 extends CglibService implements Factory {
private MethodInterceptor CGLIB$CALLBACK_0;//拦截器 private static final Method CGLIB$ getCglib $0$Method;//被代理方法 private static final MethodProxy CGLIB$ getCglib $0$Proxy;//代理方法
static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; Class localClass1 = Class.forName("cn.huangwei.classLoader.Proxy. CglibService $$EnhancerByCGLIB$$eaaaed75");//代理类 Class localClass2;//被代理类CglibService 。。。
Method[] tmp223_220 = ReflectUtils.findMethods(new String[] { " getCglib ", "()V" }, (localClass2 = Class.forName("cn.huangwei.classLoader.Proxy. CglibService ")).getDeclared- Methods()); CGLIB$ getCglib $0$Method = tmp223_220[0]; CGLIB$ getCglib $0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", " getCglib ", "CGLIB$ getCglib $0"); tmp223_220; return; }
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 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);//代理方法签名 proxy.createInfo = new MethodProxy.CreateInfo(c1, c2); return proxy; } private static class CreateInfo { 我们通过代理类的源码可以看到,代理类会获得所有在父类继承来的方法,并且会有MethodProxy与之对应,比如 Method CGLIB$getCglib $0$Method、MethodProxy CGLIB$getCglib $0$Proxy;
//被代理方法(methodProxy.invokeSuper会调用) super. getCglib (); } //代理方法 public final void getCglib () { 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$setPerson$0$Method, CGLIB$emptyArgs, CGLIB$setPerson$0$Proxy); } else { super. getCglib (); } } 主函数使用代理对象调用getCglib方法->调用拦截器->methodProxy.invokeSuper->CGLIB$getCglib $0->被代理对象getCglib方法
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);//代理方法签名 proxy.createInfo = new MethodProxy.CreateInfo(c1, c2); 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 = AbstractClassGenerator.getCurrent();
if(fromEnhancer != null) {
this.namingPolicy = fromEnhancer.getNamingPolicy();
this.strategy = fromEnhancer.getStrategy();
this.attemptLoad = fromEnhancer.getAttemptLoad();
}
}
} public Object invoke(Object obj, Object[] args) throws Throwable { try { init(); FastClassInfo fci = fastClassInfo; return fci.f1.invoke(fci.i1, obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } catch (IllegalArgumentException e) { if (fastClassInfo.i1 < 0) throw new IllegalArgumentException("Protected method: " + sig1); throw e; } }
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) { throw var4.getTargetException(); } } 上面代码调用过程就是获取到代理类对应的fastclass,并执行了代理方法,init方法就是用于生成fastclass对象,如果已存在就不创建; ------------------------------------------------------------------------------------- Cglib动态代理执行代理方法效率之所以比JDK的高是因为Cglib采用了FastClass机制,它的原理简单来说就是:为代理类和被代理类各生成一个Class,这个Class会为代理类或被代理类的方法分配一个index(int类型)。getIndex就是用于给index赋值的方法,该方法在init中会被调用,这个index当做一个入参,FastClass就可以直接定位到要调用的方法直接进行调用省去了反射的过程、 private static class FastClassInfo { FastClass f1;//被代理类FastClass FastClass f2;//代理类FastClass int i1; //被代理类的方法签名(index) int i2;//代理类的方法签名 private FastClassInfo() { } }
//根据方法签名获取index,在init方法中会被调用 public int getIndex(Signature var1) { String var10000 = var1.toString(); switch(var10000.hashCode()) { case -2077043409: if(var10000.equals("getPerson(Ljava/lang/String;)Lcom/demo/pojo/Person;")) { return 21; } break; case -2055565910: if(var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) { return 12; } break; case -1902447170: if(var10000.equals("getCglib()V")) { return 7; } break; //省略部分代码..... //根据index直接定位执行方法,在methodProxy的invoke或者invokesuper中调用 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException { eaaaed75 var10000 = (eaaaed75)var2; int var10001 = var1; try { switch(var10001) { case 7: var10000.setPerson(); return null; 。。。。。。 case 19: var10000.CGLIB$setPerson$0(); return null; //省略部分代码.... } catch (Throwable var4) { throw new InvocationTargetException(var4); } throw new IllegalArgumentException("Cannot find matching method/constructor"); }
//MethodProxy invoke/invokeSuper都调用了init() private void init() { if(this.fastClassInfo == null) { Object var1 = this.initLock; synchronized(this.initLock) { if(this.fastClassInfo == null) { MethodProxy.CreateInfo ci = this.createInfo; MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo(); fci.f1 = helper(ci, ci.c1);//如果缓存中就取出,没有就生成新的FastClass fci.f2 = helper(ci, ci.c2); fci.i1 = fci.f1.getIndex(this.sig1);//获取方法的index fci.i2 = fci.f2.getIndex(this.sig2); this.fastClassInfo = fci; this.createInfo = null; } } }
|
总过程:生成一个enhancer的实例,设定被代理类和拦截器,调用enhancer的create方法,之后能得到代理类对象proxy,并完成一些列的初始化工作,代理类对象继承了CglibService类,代理对象含有MethodInterceptor拦截器、表示被代理的方法Method对象和表示被代理的方法的MethodProxy;以及两个方法CGLIB$ getCglib $0和getCglib()方法;当主函数中调用proxy的getCglib时,会先获取拦截器,此时的拦截器,就是通过enhancer设定拦截器即CglibInterceptor的实例;然后调用intercept方法,完成回调;在CglibInterceptor类中的intercept方法中,调用methodProxy.invokeSuper方法;内部执行是,初始化fastclass,然后通过fastclass机制,获取到方法对应的index值,根据调index值用fastclass的invoke方法,此时将会调用CGLIB$ getCglib $0,即调用super父类CglibService的getCglib方法;调用结束。如果methodProxy.invoke方法,根据调index值用fastclass的invoke方法,此时将会调用getCglib造成循环调用;
1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。 2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。 3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。